portkey-admin-mcp 0.8.0 → 0.9.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 (3) hide show
  1. package/build/index.js +107 -100
  2. package/build/server.js +107 -100
  3. package/package.json +1 -1
package/build/index.js CHANGED
@@ -2684,6 +2684,14 @@ function buildConfigPayload(params) {
2684
2684
  function hasConfigSettings(config) {
2685
2685
  return config.cache !== void 0 || config.retry !== void 0 || config.strategy !== void 0 || config.targets !== void 0;
2686
2686
  }
2687
+ var createConfigSchema = z5.object(CONFIGS_TOOL_SCHEMAS.createConfig).superRefine((value, ctx) => {
2688
+ if (!hasConfigSettings(buildConfigPayload(value))) {
2689
+ ctx.addIssue({
2690
+ code: z5.ZodIssueCode.custom,
2691
+ message: "At least one config setting (cache_mode, retry_attempts, strategy_mode, or targets) must be provided"
2692
+ });
2693
+ }
2694
+ });
2687
2695
  function registerConfigsTools(server, service) {
2688
2696
  server.tool(
2689
2697
  "list_configs",
@@ -2749,25 +2757,15 @@ function registerConfigsTools(server, service) {
2749
2757
  "Create a config that defines routing, cache, retry, and targets for requests; use update_config to modify an existing one and list_config_versions for history. At least one setting is required, new configs become active immediately once referenced by a key or prompt, and the call returns the new id and version_id.",
2750
2758
  CONFIGS_TOOL_SCHEMAS.createConfig,
2751
2759
  async (params) => {
2752
- const config = buildConfigPayload(params);
2753
- if (!hasConfigSettings(config)) {
2754
- return {
2755
- content: [
2756
- {
2757
- type: "text",
2758
- text: "Error creating configuration: At least one config setting (cache_mode, retry_attempts, strategy_mode, or targets) must be provided"
2759
- }
2760
- ],
2761
- isError: true
2762
- };
2763
- }
2760
+ const validated = createConfigSchema.parse(params);
2761
+ const config = buildConfigPayload(validated);
2764
2762
  const result = await service.configs.createConfig({
2765
- name: params.name,
2763
+ name: validated.name,
2766
2764
  config,
2767
- workspace_id: params.workspace_id
2765
+ workspace_id: validated.workspace_id
2768
2766
  });
2769
2767
  return jsonResult({
2770
- message: `Successfully created configuration "${params.name}"`,
2768
+ message: `Successfully created configuration "${validated.name}"`,
2771
2769
  id: result.id,
2772
2770
  version_id: result.version_id
2773
2771
  });
@@ -3396,6 +3394,16 @@ var INTEGRATIONS_TOOL_SCHEMAS = {
3396
3394
  default_provider_slug: z8.string().optional().describe("Default slug for providers auto-created in workspaces")
3397
3395
  }
3398
3396
  };
3397
+ var updateIntegrationWorkspacesSchema = z8.object(INTEGRATIONS_TOOL_SCHEMAS.updateIntegrationWorkspaces).superRefine((value, ctx) => {
3398
+ const hasGlobalLimits = value.global_credit_limit !== void 0 || value.global_alert_threshold !== void 0 || value.global_rate_limit_rpm !== void 0;
3399
+ if (hasGlobalLimits && value.global_workspace_access_enabled === void 0) {
3400
+ ctx.addIssue({
3401
+ code: z8.ZodIssueCode.custom,
3402
+ path: ["global_workspace_access_enabled"],
3403
+ message: "global_workspace_access_enabled is required when setting global limits."
3404
+ });
3405
+ }
3406
+ });
3399
3407
  function buildIntegrationConfigurations(params) {
3400
3408
  const configurations = {};
3401
3409
  if (params.api_version !== void 0)
@@ -3673,19 +3681,8 @@ function registerIntegrationsTools(server, service) {
3673
3681
  idempotentHint: true,
3674
3682
  openWorldHint: true
3675
3683
  },
3676
- async (params) => {
3677
- const hasGlobalLimits = params.global_credit_limit !== void 0 || params.global_alert_threshold !== void 0 || params.global_rate_limit_rpm !== void 0;
3678
- if (hasGlobalLimits && params.global_workspace_access_enabled === void 0) {
3679
- return {
3680
- content: [
3681
- {
3682
- type: "text",
3683
- text: "global_workspace_access_enabled is required when setting global limits."
3684
- }
3685
- ],
3686
- isError: true
3687
- };
3688
- }
3684
+ async (rawParams) => {
3685
+ const params = updateIntegrationWorkspacesSchema.parse(rawParams);
3689
3686
  const globalUsageLimits = params.global_credit_limit !== void 0 || params.global_alert_threshold !== void 0 ? [
3690
3687
  {
3691
3688
  type: "cost",
@@ -4163,23 +4160,21 @@ var LABELS_TOOL_SCHEMAS = {
4163
4160
  label_id: z10.string().describe("Label ID to delete")
4164
4161
  }
4165
4162
  };
4163
+ var createPromptLabelSchema = z10.object(LABELS_TOOL_SCHEMAS.createPromptLabel).superRefine((value, ctx) => {
4164
+ if (!value.organisation_id && !value.workspace_id) {
4165
+ ctx.addIssue({
4166
+ code: z10.ZodIssueCode.custom,
4167
+ message: "Either organisation_id or workspace_id is required"
4168
+ });
4169
+ }
4170
+ });
4166
4171
  function registerLabelsTools(server, service) {
4167
4172
  server.tool(
4168
4173
  "create_prompt_label",
4169
4174
  "Create a prompt label for tagging prompt versions such as production, staging, or experiment. Requires either organisation_id or workspace_id to set scope, returns the new label id, and does not assign it to any versions yet.",
4170
4175
  LABELS_TOOL_SCHEMAS.createPromptLabel,
4171
- async (params) => {
4172
- if (!params.organisation_id && !params.workspace_id) {
4173
- return {
4174
- content: [
4175
- {
4176
- type: "text",
4177
- text: "Error: Either organisation_id or workspace_id is required"
4178
- }
4179
- ],
4180
- isError: true
4181
- };
4182
- }
4176
+ async (rawParams) => {
4177
+ const params = createPromptLabelSchema.parse(rawParams);
4183
4178
  const result = await service.labels.createLabel({
4184
4179
  name: params.name,
4185
4180
  organisation_id: params.organisation_id,
@@ -4589,12 +4584,13 @@ var logExportFieldSchema = z12.enum([
4589
4584
  "prompt_slug",
4590
4585
  "metadata"
4591
4586
  ]);
4592
- var getLogInputSchema = z12.object({
4587
+ var getLogShape = {
4593
4588
  log_id: z12.string().describe("Gateway log ID to retrieve"),
4594
4589
  path_format: z12.enum(["v1", "v2"]).optional().describe("Log storage path format; defaults to v1"),
4595
4590
  created_at: z12.iso.datetime({ offset: true }).optional().describe("Log creation timestamp in ISO 8601 format; required for v2"),
4596
4591
  type: z12.enum(["hooks"]).optional().describe("Set to hooks when retrieving a hook execution log")
4597
- }).superRefine((input, context) => {
4592
+ };
4593
+ var getLogSchema = z12.object(getLogShape).superRefine((input, context) => {
4598
4594
  if (input.path_format === "v2" && input.created_at === void 0) {
4599
4595
  context.addIssue({
4600
4596
  code: "custom",
@@ -4675,7 +4671,7 @@ function registerLoggingTools(server, service) {
4675
4671
  "get_log",
4676
4672
  {
4677
4673
  description: "Get one gateway request log by ID, including its request, response, usage, cost, and metadata payload when available. For path_format v2, also provide the log's created_at timestamp.",
4678
- inputSchema: getLogInputSchema,
4674
+ inputSchema: getLogShape,
4679
4675
  annotations: {
4680
4676
  title: "Get Gateway Log",
4681
4677
  readOnlyHint: true,
@@ -4684,7 +4680,8 @@ function registerLoggingTools(server, service) {
4684
4680
  openWorldHint: true
4685
4681
  }
4686
4682
  },
4687
- async (params) => {
4683
+ async (rawParams) => {
4684
+ const params = getLogSchema.parse(rawParams);
4688
4685
  const result = await service.logging.getLog(params.log_id, {
4689
4686
  path_format: params.path_format,
4690
4687
  created_at: params.created_at,
@@ -4976,6 +4973,17 @@ var MCP_INTEGRATIONS_TOOL_SCHEMAS = {
4976
4973
  ).min(1).describe("Array of workspace access updates")
4977
4974
  }
4978
4975
  };
4976
+ var createMcpIntegrationSchema = z13.object(MCP_INTEGRATIONS_TOOL_SCHEMAS.createMcpIntegration).superRefine((value, ctx) => {
4977
+ if (value.auth_type === "headers" && (!value.custom_headers || Object.keys(value.custom_headers).length === 0) && !value.secret_mappings?.some(
4978
+ (mapping) => mapping.target_field === "configurations.custom_headers"
4979
+ )) {
4980
+ ctx.addIssue({
4981
+ code: z13.ZodIssueCode.custom,
4982
+ path: ["custom_headers"],
4983
+ message: "custom_headers must be provided when auth_type is 'headers'"
4984
+ });
4985
+ }
4986
+ });
4979
4987
  function isRecord2(value) {
4980
4988
  return typeof value === "object" && value !== null;
4981
4989
  }
@@ -5054,20 +5062,8 @@ function registerMcpIntegrationsTools(server, service) {
5054
5062
  idempotentHint: false,
5055
5063
  openWorldHint: true
5056
5064
  },
5057
- async (params) => {
5058
- if (params.auth_type === "headers" && (!params.custom_headers || Object.keys(params.custom_headers).length === 0) && !params.secret_mappings?.some(
5059
- (mapping) => mapping.target_field === "configurations.custom_headers"
5060
- )) {
5061
- return {
5062
- content: [
5063
- {
5064
- type: "text",
5065
- text: "Error: custom_headers must be provided when auth_type is 'headers'"
5066
- }
5067
- ],
5068
- isError: true
5069
- };
5070
- }
5065
+ async (rawParams) => {
5066
+ const params = createMcpIntegrationSchema.parse(rawParams);
5071
5067
  const { custom_headers, ...rest } = params;
5072
5068
  const result = await service.mcpIntegrations.createMcpIntegration({
5073
5069
  ...rest,
@@ -5904,6 +5900,28 @@ var PROMPTS_TOOL_SCHEMAS = {
5904
5900
  )
5905
5901
  }
5906
5902
  };
5903
+ var createPromptSchema = z17.object(PROMPTS_TOOL_SCHEMAS.createPrompt).superRefine((value, ctx) => {
5904
+ if (!value.model && !value.ai_model_id && !value.finetune_id) {
5905
+ ctx.addIssue({
5906
+ code: z17.ZodIssueCode.custom,
5907
+ message: "At least one of model, ai_model_id, or finetune_id must be provided"
5908
+ });
5909
+ }
5910
+ if (value.string === void 0 && value.messages === void 0) {
5911
+ ctx.addIssue({
5912
+ code: z17.ZodIssueCode.custom,
5913
+ message: "Provide either string or messages"
5914
+ });
5915
+ }
5916
+ });
5917
+ var migratePromptSchema = z17.object(PROMPTS_TOOL_SCHEMAS.migratePrompt).superRefine((value, ctx) => {
5918
+ if (value.string === void 0 && value.messages === void 0) {
5919
+ ctx.addIssue({
5920
+ code: z17.ZodIssueCode.custom,
5921
+ message: "Provide either string or messages"
5922
+ });
5923
+ }
5924
+ });
5907
5925
  function normalizePromptTemplateString(params) {
5908
5926
  if (params.string !== void 0) {
5909
5927
  return params.string;
@@ -5978,30 +5996,9 @@ function registerPromptsTools(server, service) {
5978
5996
  "create_prompt",
5979
5997
  "Create a new prompt template and initial version. Use this for first-time setup; use migrate_prompt for idempotent CI/CD flows. Accepts plain text or structured chat messages, creates a new version immediately, and returns the prompt id, slug, and version id. For multi-message chat prompts pass messages (preferred) or a JSON-encoded array as string.",
5980
5998
  PROMPTS_TOOL_SCHEMAS.createPrompt,
5981
- async (params) => {
5982
- if (!params.model && !params.ai_model_id && !params.finetune_id) {
5983
- return {
5984
- content: [
5985
- {
5986
- type: "text",
5987
- text: "Error creating prompt: At least one of model, ai_model_id, or finetune_id must be provided"
5988
- }
5989
- ],
5990
- isError: true
5991
- };
5992
- }
5999
+ async (rawParams) => {
6000
+ const params = createPromptSchema.parse(rawParams);
5993
6001
  const templateString = normalizePromptTemplateString(params);
5994
- if (templateString === void 0) {
5995
- return {
5996
- content: [
5997
- {
5998
- type: "text",
5999
- text: "Error creating prompt: Provide either string or messages"
6000
- }
6001
- ],
6002
- isError: true
6003
- };
6004
- }
6005
6002
  if (params.dry_run) {
6006
6003
  return jsonResult({
6007
6004
  dry_run: true,
@@ -6256,19 +6253,9 @@ function registerPromptsTools(server, service) {
6256
6253
  idempotentHint: true,
6257
6254
  openWorldHint: false
6258
6255
  },
6259
- async (params) => {
6256
+ async (rawParams) => {
6257
+ const params = migratePromptSchema.parse(rawParams);
6260
6258
  const templateString = normalizePromptTemplateString(params);
6261
- if (templateString === void 0) {
6262
- return {
6263
- content: [
6264
- {
6265
- type: "text",
6266
- text: "Error migrating prompt: Provide either string or messages"
6267
- }
6268
- ],
6269
- isError: true
6270
- };
6271
- }
6272
6259
  const result = await service.prompts.migratePrompt({
6273
6260
  name: params.name,
6274
6261
  app: params.app,
@@ -7234,7 +7221,7 @@ var scimWorkspaceMappingBaseShape = {
7234
7221
  workspace_id: z22.string().describe("Portkey workspace ID that the SCIM group should access"),
7235
7222
  role: z22.enum(["admin", "member", "manager"]).describe("Workspace role automatically granted to group members")
7236
7223
  };
7237
- var createScimWorkspaceMappingInputSchema = z22.object({
7224
+ var createScimWorkspaceMappingShape = {
7238
7225
  ...scimWorkspaceMappingBaseShape,
7239
7226
  scim_group_id: z22.string().min(1).optional().describe(
7240
7227
  "Existing identity-provider SCIM group ID; provide this or scim_group_name, but not both"
@@ -7242,7 +7229,8 @@ var createScimWorkspaceMappingInputSchema = z22.object({
7242
7229
  scim_group_name: z22.string().min(1).optional().describe(
7243
7230
  "Existing SCIM group display name; provide this or scim_group_id, but not both"
7244
7231
  )
7245
- }).superRefine((input, context) => {
7232
+ };
7233
+ var createScimWorkspaceMappingSchema = z22.object(createScimWorkspaceMappingShape).superRefine((input, context) => {
7246
7234
  if (Boolean(input.scim_group_id) === Boolean(input.scim_group_name)) {
7247
7235
  context.addIssue({
7248
7236
  code: "custom",
@@ -7397,7 +7385,7 @@ function registerWorkspacesTools(server, service) {
7397
7385
  "create_scim_workspace_mapping",
7398
7386
  {
7399
7387
  description: "Map one identity-provider SCIM group to a Portkey workspace role so current and future group members receive access automatically. Provide exactly one of scim_group_id or scim_group_name; a name can pre-create the Portkey SCIM group before the IdP provisions it. Use list_scim_groups to discover existing groups and list_workspaces for the workspace ID. This changes access provisioning and is distinct from add_workspace_member, which grants one user directly.",
7400
- inputSchema: createScimWorkspaceMappingInputSchema,
7388
+ inputSchema: createScimWorkspaceMappingShape,
7401
7389
  annotations: {
7402
7390
  title: "Create SCIM Workspace Mapping",
7403
7391
  readOnlyHint: false,
@@ -7406,7 +7394,8 @@ function registerWorkspacesTools(server, service) {
7406
7394
  openWorldHint: true
7407
7395
  }
7408
7396
  },
7409
- async (params) => {
7397
+ async (rawParams) => {
7398
+ const params = createScimWorkspaceMappingSchema.parse(rawParams);
7410
7399
  let request;
7411
7400
  if (params.scim_group_id !== void 0) {
7412
7401
  request = {
@@ -7767,7 +7756,25 @@ function augmentToolDescription(toolName, description) {
7767
7756
  }
7768
7757
  return `${description} ${ENTERPRISE_GATED_DESCRIPTION_NOTE}`;
7769
7758
  }
7759
+ function formatZodIssues(error) {
7760
+ return error.issues.map((issue) => {
7761
+ const path = issue.path.join(".");
7762
+ if (!path) {
7763
+ return issue.message;
7764
+ }
7765
+ const namesPath = new RegExp(`\\b${escapeRegExp(path)}\\b`).test(
7766
+ issue.message
7767
+ );
7768
+ return namesPath ? issue.message : `${path}: ${issue.message}`;
7769
+ }).join("; ");
7770
+ }
7771
+ function escapeRegExp(value) {
7772
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7773
+ }
7770
7774
  function getToolErrorMessage(error) {
7775
+ if (error instanceof z23.ZodError) {
7776
+ return formatZodIssues(error);
7777
+ }
7771
7778
  if (error instanceof Error && error.message) {
7772
7779
  return error.message;
7773
7780
  }
@@ -7914,14 +7921,14 @@ function wrapToolCallback(toolName, callback) {
7914
7921
  return normalizeToolResult(await callback(...args));
7915
7922
  } catch (error) {
7916
7923
  const message = getToolErrorMessage(error);
7924
+ const isValidationError = error instanceof z23.ZodError;
7925
+ const text = isValidationError ? `Invalid arguments for "${toolName}": ${message}` : `Tool "${toolName}" failed: ${message}`;
7917
7926
  Logger.error("Tool callback failed", {
7918
7927
  error: message,
7919
7928
  metadata: { toolName }
7920
7929
  });
7921
7930
  return normalizeToolResult({
7922
- content: [
7923
- { type: "text", text: `Tool "${toolName}" failed: ${message}` }
7924
- ],
7931
+ content: [{ type: "text", text }],
7925
7932
  isError: true
7926
7933
  });
7927
7934
  }
package/build/server.js CHANGED
@@ -2701,6 +2701,14 @@ function buildConfigPayload(params) {
2701
2701
  function hasConfigSettings(config) {
2702
2702
  return config.cache !== void 0 || config.retry !== void 0 || config.strategy !== void 0 || config.targets !== void 0;
2703
2703
  }
2704
+ var createConfigSchema = z5.object(CONFIGS_TOOL_SCHEMAS.createConfig).superRefine((value, ctx) => {
2705
+ if (!hasConfigSettings(buildConfigPayload(value))) {
2706
+ ctx.addIssue({
2707
+ code: z5.ZodIssueCode.custom,
2708
+ message: "At least one config setting (cache_mode, retry_attempts, strategy_mode, or targets) must be provided"
2709
+ });
2710
+ }
2711
+ });
2704
2712
  function registerConfigsTools(server, service) {
2705
2713
  server.tool(
2706
2714
  "list_configs",
@@ -2766,25 +2774,15 @@ function registerConfigsTools(server, service) {
2766
2774
  "Create a config that defines routing, cache, retry, and targets for requests; use update_config to modify an existing one and list_config_versions for history. At least one setting is required, new configs become active immediately once referenced by a key or prompt, and the call returns the new id and version_id.",
2767
2775
  CONFIGS_TOOL_SCHEMAS.createConfig,
2768
2776
  async (params) => {
2769
- const config = buildConfigPayload(params);
2770
- if (!hasConfigSettings(config)) {
2771
- return {
2772
- content: [
2773
- {
2774
- type: "text",
2775
- text: "Error creating configuration: At least one config setting (cache_mode, retry_attempts, strategy_mode, or targets) must be provided"
2776
- }
2777
- ],
2778
- isError: true
2779
- };
2780
- }
2777
+ const validated = createConfigSchema.parse(params);
2778
+ const config = buildConfigPayload(validated);
2781
2779
  const result = await service.configs.createConfig({
2782
- name: params.name,
2780
+ name: validated.name,
2783
2781
  config,
2784
- workspace_id: params.workspace_id
2782
+ workspace_id: validated.workspace_id
2785
2783
  });
2786
2784
  return jsonResult({
2787
- message: `Successfully created configuration "${params.name}"`,
2785
+ message: `Successfully created configuration "${validated.name}"`,
2788
2786
  id: result.id,
2789
2787
  version_id: result.version_id
2790
2788
  });
@@ -3413,6 +3411,16 @@ var INTEGRATIONS_TOOL_SCHEMAS = {
3413
3411
  default_provider_slug: z8.string().optional().describe("Default slug for providers auto-created in workspaces")
3414
3412
  }
3415
3413
  };
3414
+ var updateIntegrationWorkspacesSchema = z8.object(INTEGRATIONS_TOOL_SCHEMAS.updateIntegrationWorkspaces).superRefine((value, ctx) => {
3415
+ const hasGlobalLimits = value.global_credit_limit !== void 0 || value.global_alert_threshold !== void 0 || value.global_rate_limit_rpm !== void 0;
3416
+ if (hasGlobalLimits && value.global_workspace_access_enabled === void 0) {
3417
+ ctx.addIssue({
3418
+ code: z8.ZodIssueCode.custom,
3419
+ path: ["global_workspace_access_enabled"],
3420
+ message: "global_workspace_access_enabled is required when setting global limits."
3421
+ });
3422
+ }
3423
+ });
3416
3424
  function buildIntegrationConfigurations(params) {
3417
3425
  const configurations = {};
3418
3426
  if (params.api_version !== void 0)
@@ -3690,19 +3698,8 @@ function registerIntegrationsTools(server, service) {
3690
3698
  idempotentHint: true,
3691
3699
  openWorldHint: true
3692
3700
  },
3693
- async (params) => {
3694
- const hasGlobalLimits = params.global_credit_limit !== void 0 || params.global_alert_threshold !== void 0 || params.global_rate_limit_rpm !== void 0;
3695
- if (hasGlobalLimits && params.global_workspace_access_enabled === void 0) {
3696
- return {
3697
- content: [
3698
- {
3699
- type: "text",
3700
- text: "global_workspace_access_enabled is required when setting global limits."
3701
- }
3702
- ],
3703
- isError: true
3704
- };
3705
- }
3701
+ async (rawParams) => {
3702
+ const params = updateIntegrationWorkspacesSchema.parse(rawParams);
3706
3703
  const globalUsageLimits = params.global_credit_limit !== void 0 || params.global_alert_threshold !== void 0 ? [
3707
3704
  {
3708
3705
  type: "cost",
@@ -4180,23 +4177,21 @@ var LABELS_TOOL_SCHEMAS = {
4180
4177
  label_id: z10.string().describe("Label ID to delete")
4181
4178
  }
4182
4179
  };
4180
+ var createPromptLabelSchema = z10.object(LABELS_TOOL_SCHEMAS.createPromptLabel).superRefine((value, ctx) => {
4181
+ if (!value.organisation_id && !value.workspace_id) {
4182
+ ctx.addIssue({
4183
+ code: z10.ZodIssueCode.custom,
4184
+ message: "Either organisation_id or workspace_id is required"
4185
+ });
4186
+ }
4187
+ });
4183
4188
  function registerLabelsTools(server, service) {
4184
4189
  server.tool(
4185
4190
  "create_prompt_label",
4186
4191
  "Create a prompt label for tagging prompt versions such as production, staging, or experiment. Requires either organisation_id or workspace_id to set scope, returns the new label id, and does not assign it to any versions yet.",
4187
4192
  LABELS_TOOL_SCHEMAS.createPromptLabel,
4188
- async (params) => {
4189
- if (!params.organisation_id && !params.workspace_id) {
4190
- return {
4191
- content: [
4192
- {
4193
- type: "text",
4194
- text: "Error: Either organisation_id or workspace_id is required"
4195
- }
4196
- ],
4197
- isError: true
4198
- };
4199
- }
4193
+ async (rawParams) => {
4194
+ const params = createPromptLabelSchema.parse(rawParams);
4200
4195
  const result = await service.labels.createLabel({
4201
4196
  name: params.name,
4202
4197
  organisation_id: params.organisation_id,
@@ -4606,12 +4601,13 @@ var logExportFieldSchema = z12.enum([
4606
4601
  "prompt_slug",
4607
4602
  "metadata"
4608
4603
  ]);
4609
- var getLogInputSchema = z12.object({
4604
+ var getLogShape = {
4610
4605
  log_id: z12.string().describe("Gateway log ID to retrieve"),
4611
4606
  path_format: z12.enum(["v1", "v2"]).optional().describe("Log storage path format; defaults to v1"),
4612
4607
  created_at: z12.iso.datetime({ offset: true }).optional().describe("Log creation timestamp in ISO 8601 format; required for v2"),
4613
4608
  type: z12.enum(["hooks"]).optional().describe("Set to hooks when retrieving a hook execution log")
4614
- }).superRefine((input, context) => {
4609
+ };
4610
+ var getLogSchema = z12.object(getLogShape).superRefine((input, context) => {
4615
4611
  if (input.path_format === "v2" && input.created_at === void 0) {
4616
4612
  context.addIssue({
4617
4613
  code: "custom",
@@ -4692,7 +4688,7 @@ function registerLoggingTools(server, service) {
4692
4688
  "get_log",
4693
4689
  {
4694
4690
  description: "Get one gateway request log by ID, including its request, response, usage, cost, and metadata payload when available. For path_format v2, also provide the log's created_at timestamp.",
4695
- inputSchema: getLogInputSchema,
4691
+ inputSchema: getLogShape,
4696
4692
  annotations: {
4697
4693
  title: "Get Gateway Log",
4698
4694
  readOnlyHint: true,
@@ -4701,7 +4697,8 @@ function registerLoggingTools(server, service) {
4701
4697
  openWorldHint: true
4702
4698
  }
4703
4699
  },
4704
- async (params) => {
4700
+ async (rawParams) => {
4701
+ const params = getLogSchema.parse(rawParams);
4705
4702
  const result = await service.logging.getLog(params.log_id, {
4706
4703
  path_format: params.path_format,
4707
4704
  created_at: params.created_at,
@@ -4993,6 +4990,17 @@ var MCP_INTEGRATIONS_TOOL_SCHEMAS = {
4993
4990
  ).min(1).describe("Array of workspace access updates")
4994
4991
  }
4995
4992
  };
4993
+ var createMcpIntegrationSchema = z13.object(MCP_INTEGRATIONS_TOOL_SCHEMAS.createMcpIntegration).superRefine((value, ctx) => {
4994
+ if (value.auth_type === "headers" && (!value.custom_headers || Object.keys(value.custom_headers).length === 0) && !value.secret_mappings?.some(
4995
+ (mapping) => mapping.target_field === "configurations.custom_headers"
4996
+ )) {
4997
+ ctx.addIssue({
4998
+ code: z13.ZodIssueCode.custom,
4999
+ path: ["custom_headers"],
5000
+ message: "custom_headers must be provided when auth_type is 'headers'"
5001
+ });
5002
+ }
5003
+ });
4996
5004
  function isRecord2(value) {
4997
5005
  return typeof value === "object" && value !== null;
4998
5006
  }
@@ -5071,20 +5079,8 @@ function registerMcpIntegrationsTools(server, service) {
5071
5079
  idempotentHint: false,
5072
5080
  openWorldHint: true
5073
5081
  },
5074
- async (params) => {
5075
- if (params.auth_type === "headers" && (!params.custom_headers || Object.keys(params.custom_headers).length === 0) && !params.secret_mappings?.some(
5076
- (mapping) => mapping.target_field === "configurations.custom_headers"
5077
- )) {
5078
- return {
5079
- content: [
5080
- {
5081
- type: "text",
5082
- text: "Error: custom_headers must be provided when auth_type is 'headers'"
5083
- }
5084
- ],
5085
- isError: true
5086
- };
5087
- }
5082
+ async (rawParams) => {
5083
+ const params = createMcpIntegrationSchema.parse(rawParams);
5088
5084
  const { custom_headers, ...rest } = params;
5089
5085
  const result = await service.mcpIntegrations.createMcpIntegration({
5090
5086
  ...rest,
@@ -5921,6 +5917,28 @@ var PROMPTS_TOOL_SCHEMAS = {
5921
5917
  )
5922
5918
  }
5923
5919
  };
5920
+ var createPromptSchema = z17.object(PROMPTS_TOOL_SCHEMAS.createPrompt).superRefine((value, ctx) => {
5921
+ if (!value.model && !value.ai_model_id && !value.finetune_id) {
5922
+ ctx.addIssue({
5923
+ code: z17.ZodIssueCode.custom,
5924
+ message: "At least one of model, ai_model_id, or finetune_id must be provided"
5925
+ });
5926
+ }
5927
+ if (value.string === void 0 && value.messages === void 0) {
5928
+ ctx.addIssue({
5929
+ code: z17.ZodIssueCode.custom,
5930
+ message: "Provide either string or messages"
5931
+ });
5932
+ }
5933
+ });
5934
+ var migratePromptSchema = z17.object(PROMPTS_TOOL_SCHEMAS.migratePrompt).superRefine((value, ctx) => {
5935
+ if (value.string === void 0 && value.messages === void 0) {
5936
+ ctx.addIssue({
5937
+ code: z17.ZodIssueCode.custom,
5938
+ message: "Provide either string or messages"
5939
+ });
5940
+ }
5941
+ });
5924
5942
  function normalizePromptTemplateString(params) {
5925
5943
  if (params.string !== void 0) {
5926
5944
  return params.string;
@@ -5995,30 +6013,9 @@ function registerPromptsTools(server, service) {
5995
6013
  "create_prompt",
5996
6014
  "Create a new prompt template and initial version. Use this for first-time setup; use migrate_prompt for idempotent CI/CD flows. Accepts plain text or structured chat messages, creates a new version immediately, and returns the prompt id, slug, and version id. For multi-message chat prompts pass messages (preferred) or a JSON-encoded array as string.",
5997
6015
  PROMPTS_TOOL_SCHEMAS.createPrompt,
5998
- async (params) => {
5999
- if (!params.model && !params.ai_model_id && !params.finetune_id) {
6000
- return {
6001
- content: [
6002
- {
6003
- type: "text",
6004
- text: "Error creating prompt: At least one of model, ai_model_id, or finetune_id must be provided"
6005
- }
6006
- ],
6007
- isError: true
6008
- };
6009
- }
6016
+ async (rawParams) => {
6017
+ const params = createPromptSchema.parse(rawParams);
6010
6018
  const templateString = normalizePromptTemplateString(params);
6011
- if (templateString === void 0) {
6012
- return {
6013
- content: [
6014
- {
6015
- type: "text",
6016
- text: "Error creating prompt: Provide either string or messages"
6017
- }
6018
- ],
6019
- isError: true
6020
- };
6021
- }
6022
6019
  if (params.dry_run) {
6023
6020
  return jsonResult({
6024
6021
  dry_run: true,
@@ -6273,19 +6270,9 @@ function registerPromptsTools(server, service) {
6273
6270
  idempotentHint: true,
6274
6271
  openWorldHint: false
6275
6272
  },
6276
- async (params) => {
6273
+ async (rawParams) => {
6274
+ const params = migratePromptSchema.parse(rawParams);
6277
6275
  const templateString = normalizePromptTemplateString(params);
6278
- if (templateString === void 0) {
6279
- return {
6280
- content: [
6281
- {
6282
- type: "text",
6283
- text: "Error migrating prompt: Provide either string or messages"
6284
- }
6285
- ],
6286
- isError: true
6287
- };
6288
- }
6289
6276
  const result = await service.prompts.migratePrompt({
6290
6277
  name: params.name,
6291
6278
  app: params.app,
@@ -7251,7 +7238,7 @@ var scimWorkspaceMappingBaseShape = {
7251
7238
  workspace_id: z22.string().describe("Portkey workspace ID that the SCIM group should access"),
7252
7239
  role: z22.enum(["admin", "member", "manager"]).describe("Workspace role automatically granted to group members")
7253
7240
  };
7254
- var createScimWorkspaceMappingInputSchema = z22.object({
7241
+ var createScimWorkspaceMappingShape = {
7255
7242
  ...scimWorkspaceMappingBaseShape,
7256
7243
  scim_group_id: z22.string().min(1).optional().describe(
7257
7244
  "Existing identity-provider SCIM group ID; provide this or scim_group_name, but not both"
@@ -7259,7 +7246,8 @@ var createScimWorkspaceMappingInputSchema = z22.object({
7259
7246
  scim_group_name: z22.string().min(1).optional().describe(
7260
7247
  "Existing SCIM group display name; provide this or scim_group_id, but not both"
7261
7248
  )
7262
- }).superRefine((input, context) => {
7249
+ };
7250
+ var createScimWorkspaceMappingSchema = z22.object(createScimWorkspaceMappingShape).superRefine((input, context) => {
7263
7251
  if (Boolean(input.scim_group_id) === Boolean(input.scim_group_name)) {
7264
7252
  context.addIssue({
7265
7253
  code: "custom",
@@ -7414,7 +7402,7 @@ function registerWorkspacesTools(server, service) {
7414
7402
  "create_scim_workspace_mapping",
7415
7403
  {
7416
7404
  description: "Map one identity-provider SCIM group to a Portkey workspace role so current and future group members receive access automatically. Provide exactly one of scim_group_id or scim_group_name; a name can pre-create the Portkey SCIM group before the IdP provisions it. Use list_scim_groups to discover existing groups and list_workspaces for the workspace ID. This changes access provisioning and is distinct from add_workspace_member, which grants one user directly.",
7417
- inputSchema: createScimWorkspaceMappingInputSchema,
7405
+ inputSchema: createScimWorkspaceMappingShape,
7418
7406
  annotations: {
7419
7407
  title: "Create SCIM Workspace Mapping",
7420
7408
  readOnlyHint: false,
@@ -7423,7 +7411,8 @@ function registerWorkspacesTools(server, service) {
7423
7411
  openWorldHint: true
7424
7412
  }
7425
7413
  },
7426
- async (params) => {
7414
+ async (rawParams) => {
7415
+ const params = createScimWorkspaceMappingSchema.parse(rawParams);
7427
7416
  let request;
7428
7417
  if (params.scim_group_id !== void 0) {
7429
7418
  request = {
@@ -7784,7 +7773,25 @@ function augmentToolDescription(toolName, description) {
7784
7773
  }
7785
7774
  return `${description} ${ENTERPRISE_GATED_DESCRIPTION_NOTE}`;
7786
7775
  }
7776
+ function formatZodIssues(error) {
7777
+ return error.issues.map((issue) => {
7778
+ const path = issue.path.join(".");
7779
+ if (!path) {
7780
+ return issue.message;
7781
+ }
7782
+ const namesPath = new RegExp(`\\b${escapeRegExp(path)}\\b`).test(
7783
+ issue.message
7784
+ );
7785
+ return namesPath ? issue.message : `${path}: ${issue.message}`;
7786
+ }).join("; ");
7787
+ }
7788
+ function escapeRegExp(value) {
7789
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7790
+ }
7787
7791
  function getToolErrorMessage(error) {
7792
+ if (error instanceof z23.ZodError) {
7793
+ return formatZodIssues(error);
7794
+ }
7788
7795
  if (error instanceof Error && error.message) {
7789
7796
  return error.message;
7790
7797
  }
@@ -7931,14 +7938,14 @@ function wrapToolCallback(toolName, callback) {
7931
7938
  return normalizeToolResult(await callback(...args));
7932
7939
  } catch (error) {
7933
7940
  const message = getToolErrorMessage(error);
7941
+ const isValidationError = error instanceof z23.ZodError;
7942
+ const text = isValidationError ? `Invalid arguments for "${toolName}": ${message}` : `Tool "${toolName}" failed: ${message}`;
7934
7943
  Logger.error("Tool callback failed", {
7935
7944
  error: message,
7936
7945
  metadata: { toolName }
7937
7946
  });
7938
7947
  return normalizeToolResult({
7939
- content: [
7940
- { type: "text", text: `Tool "${toolName}" failed: ${message}` }
7941
- ],
7948
+ content: [{ type: "text", text }],
7942
7949
  isError: true
7943
7950
  });
7944
7951
  }
package/package.json CHANGED
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "name": "portkey-admin-mcp",
55
55
  "mcpName": "io.github.CodesWhat/portkey-admin-mcp",
56
- "version": "0.8.0",
56
+ "version": "0.9.0",
57
57
  "main": "build/index.js",
58
58
  "keywords": [
59
59
  "mcp",