@rymi/mcp 2.8.2 → 2.10.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 (2) hide show
  1. package/dist/index.js +435 -105
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -187,6 +187,7 @@ var init_studioCatalog = __esm({
187
187
  "llama-4-scout",
188
188
  "deepseek-v4-flash",
189
189
  "deepseek-v4-pro",
190
+ "grok-4.7",
190
191
  "grok-4-1-fast",
191
192
  "grok-3-mini",
192
193
  "grok-3-mini-fast",
@@ -250,6 +251,7 @@ var init_studioCatalog = __esm({
250
251
  ],
251
252
  tts: [
252
253
  "aura-2",
254
+ "flux-tts",
253
255
  "gemini-2.5-pro-preview-tts",
254
256
  "sonic-3.5",
255
257
  "sonic-turbo",
@@ -1837,7 +1839,7 @@ var init_agentConfigSchema = __esm({
1837
1839
  },
1838
1840
  // ── Runtime Timing ──────────────────────────────────────────────────────
1839
1841
  { key: "maxTurnLength", label: "Max Turn Length", description: "Maximum number of conversational turns.", default: 50, type: { kind: "number", min: 1, max: 200 }, apiPath: "advanced.maxTurnLength", section: "advanced", editableIn: "both" },
1840
- { key: "postSilenceHangup", label: "Post-Silence Hangup", description: "Hang up after this many seconds of silence.", default: 30, type: { kind: "number", min: 1, max: 6e4, unit: "s" }, apiPath: "advanced.postSilenceHangup", section: "advanced", editableIn: "both" },
1842
+ { key: "postSilenceHangup", label: "Post-Silence Hangup", description: "Hang up after this many seconds of silence.", default: 60, type: { kind: "number", min: 1, max: 6e4, unit: "s" }, apiPath: "advanced.postSilenceHangup", section: "advanced", editableIn: "both" },
1841
1843
  { key: "silencePromptMaxCount", label: "Silence Check-ins", description: "How many times the agent checks on a silent caller before the silence goodbye.", default: 2, type: { kind: "number", min: 1, max: 3 }, apiPath: "advanced.silencePromptMaxCount", section: "advanced", editableIn: "both" },
1842
1844
  { key: "silenceHangupMessage", label: "Silence Goodbye", description: "Exact line spoken before a silence hangup. Leave empty to let the agent say a short goodbye in the caller's language.", default: "", type: { kind: "string", maxLength: 200 }, apiPath: "advanced.silenceHangupMessage", section: "advanced", editableIn: "both" },
1843
1845
  { key: "maxCallDuration", label: "Max Call Duration", description: "Hard limit on call length.", default: 600, type: { kind: "number", min: 30, max: 7200, unit: "s" }, apiPath: "advanced.maxCallDuration", section: "advanced", editableIn: "both" },
@@ -2502,6 +2504,7 @@ var init_pricing = __esm({
2502
2504
  "llama-4-scout": 56e-5,
2503
2505
  "deepseek-v4-flash": 34e-5,
2504
2506
  "deepseek-v4-pro": 418e-5,
2507
+ "grok-4.7": 64e-4,
2505
2508
  "grok-4-1-fast": 56e-5,
2506
2509
  "grok-3-mini": 64e-5,
2507
2510
  "grok-3-mini-fast": 48e-5,
@@ -2531,10 +2534,12 @@ var init_pricing = __esm({
2531
2534
  "Qwen/Qwen2.5-72B-Instruct": 22e-4,
2532
2535
  "deepseek-ai/DeepSeek-V3": 14e-4,
2533
2536
  "sarvam-30b": 10526e-8,
2534
- "sarvam-105b": 77053e-8,
2535
- "sarvam-105b-conversations": 77053e-8,
2537
+ "sarvam-105b": 0.01024,
2538
+ // measured 2026-10-25, see rates.py
2539
+ "sarvam-105b-conversations": 0.01024,
2536
2540
  // TTS
2537
2541
  "aura-2": 0.027,
2542
+ "flux-tts": 0.0405,
2538
2543
  "gemini-2.5-flash-preview-tts": 0.015,
2539
2544
  "gemini-3.1-flash-tts-preview": 0.015,
2540
2545
  "gpt-4o-mini-tts": 0.015,
@@ -6948,6 +6953,263 @@ var init_supportedCountries = __esm({
6948
6953
  }
6949
6954
  });
6950
6955
 
6956
+ // ../shared-types/dist/whatsappTemplates.js
6957
+ function hasModelSlot(entry) {
6958
+ if (entry.variables?.some((v) => v.source === "model"))
6959
+ return true;
6960
+ if (entry.buttons?.some((b) => b.source === "model"))
6961
+ return true;
6962
+ return false;
6963
+ }
6964
+ function valueRuleError(value) {
6965
+ if (typeof value !== "string")
6966
+ return "must be a string";
6967
+ if (value.includes("\n") || value.includes("\r")) {
6968
+ return "must not contain newlines";
6969
+ }
6970
+ if (value.includes(" ")) {
6971
+ return "must not contain tabs";
6972
+ }
6973
+ if (/[ ]{5,}/.test(value)) {
6974
+ return "must not contain more than 4 consecutive spaces";
6975
+ }
6976
+ if (value.length > 300) {
6977
+ return `exceeds 300 characters (${value.length})`;
6978
+ }
6979
+ return null;
6980
+ }
6981
+ function langCode(key) {
6982
+ const k = key.trim().toLowerCase();
6983
+ if (k === "english")
6984
+ return "en";
6985
+ if (k === "hindi")
6986
+ return "hi";
6987
+ return k;
6988
+ }
6989
+ function resolveLangTag(key) {
6990
+ const k = key.trim().toLowerCase();
6991
+ if (k === "english")
6992
+ return "en";
6993
+ if (k === "hindi")
6994
+ return "hi";
6995
+ if (k === "hinglish")
6996
+ return "hinglish";
6997
+ return k;
6998
+ }
6999
+ function pickSyncedTemplate(templates, name, languageKey) {
7000
+ if (!templates || !Array.isArray(templates) || templates.length === 0)
7001
+ return null;
7002
+ const matching = templates.filter((t) => t.name === name);
7003
+ if (matching.length === 0)
7004
+ return null;
7005
+ if (matching.length === 1)
7006
+ return matching[0];
7007
+ const target = langCode(languageKey).toLowerCase();
7008
+ const directMatch = matching.find((t) => t.language.toLowerCase().startsWith(target));
7009
+ if (directMatch)
7010
+ return directMatch;
7011
+ if (languageKey.trim().toLowerCase() === "hinglish") {
7012
+ const enFallback = matching.find((t) => t.language.toLowerCase().startsWith("en"));
7013
+ if (enFallback)
7014
+ return enFallback;
7015
+ }
7016
+ return null;
7017
+ }
7018
+ function templateShapeError(entry, synced) {
7019
+ if (synced.variable_count !== void 0 && synced.variable_count !== null) {
7020
+ const entryVarCount = entry.variables?.length ?? 0;
7021
+ if (entryVarCount !== synced.variable_count) {
7022
+ return `variable count mismatch: entry has ${entryVarCount}, synced template has ${synced.variable_count}`;
7023
+ }
7024
+ }
7025
+ if (synced.buttons !== void 0 && synced.buttons !== null) {
7026
+ const entryButtons = entry.buttons ?? [];
7027
+ const syncedButtons = synced.buttons;
7028
+ if (entryButtons.length !== syncedButtons.length) {
7029
+ return `button count mismatch: entry has ${entryButtons.length}, synced template has ${syncedButtons.length}`;
7030
+ }
7031
+ const syncedByIndex = new Map(syncedButtons.map((b) => [b.index, b]));
7032
+ for (const eb of entryButtons) {
7033
+ const sb = syncedByIndex.get(eb.index);
7034
+ if (!sb) {
7035
+ return `button index ${eb.index} missing in synced template`;
7036
+ }
7037
+ if (eb.type !== sb.type) {
7038
+ return `button index ${eb.index} type mismatch: entry has ${eb.type}, synced template has ${sb.type}`;
7039
+ }
7040
+ }
7041
+ }
7042
+ return null;
7043
+ }
7044
+ function buildComponents(entry, languageKey, values, buttonValues = {}) {
7045
+ const components = [];
7046
+ const btnVals = buttonValues ?? {};
7047
+ if (values && values.length > 0) {
7048
+ components.push({
7049
+ type: "body",
7050
+ parameters: values.map((text) => ({ type: "text", text }))
7051
+ });
7052
+ }
7053
+ const buttons = entry.buttons ?? [];
7054
+ const sortedButtons = [...buttons].sort((a, b) => a.index - b.index);
7055
+ for (const btn of sortedButtons) {
7056
+ const idxStr = String(btn.index);
7057
+ if (btn.type === "url") {
7058
+ const val = btnVals[btn.index] ?? btnVals[idxStr] ?? btn.value;
7059
+ if (val !== void 0 && val !== null && String(val) !== "") {
7060
+ components.push({
7061
+ type: "button",
7062
+ sub_type: "url",
7063
+ index: idxStr,
7064
+ parameters: [{ type: "text", text: String(val) }]
7065
+ });
7066
+ }
7067
+ } else if (btn.type === "quick_reply") {
7068
+ let payload = btnVals[btn.index] ?? btnVals[idxStr];
7069
+ if (!payload && btn.payload) {
7070
+ payload = btn.payload.replace(/\{lang\}/g, resolveLangTag(languageKey));
7071
+ }
7072
+ if (payload !== void 0 && payload !== null && String(payload) !== "") {
7073
+ components.push({
7074
+ type: "button",
7075
+ sub_type: "quick_reply",
7076
+ index: idxStr,
7077
+ parameters: [{ type: "payload", payload: String(payload) }]
7078
+ });
7079
+ }
7080
+ }
7081
+ }
7082
+ return components;
7083
+ }
7084
+ function whatsappSenderId(creds, tenantId) {
7085
+ const pnId = creds?.phone_number_id?.trim();
7086
+ if (pnId)
7087
+ return pnId;
7088
+ const src = creds?.src_phone?.trim();
7089
+ if (src)
7090
+ return src;
7091
+ return `simulated:${tenantId || "unknown"}`;
7092
+ }
7093
+ function isCountryAllowed(phone, allowedCountries) {
7094
+ if (!phone || typeof phone !== "string")
7095
+ return false;
7096
+ const country = phoneNumberCountry(phone);
7097
+ if (!country)
7098
+ return false;
7099
+ const allowed = allowedCountries && allowedCountries.length > 0 ? allowedCountries.map((c) => c.toUpperCase()) : SUPPORTED_COUNTRY_CODES;
7100
+ return allowed.includes(country.toUpperCase());
7101
+ }
7102
+ function whatsappTemplateBindingErrors(tools) {
7103
+ if (!Array.isArray(tools))
7104
+ return [];
7105
+ const errors = [];
7106
+ for (const tool of tools) {
7107
+ if (!tool || typeof tool !== "object")
7108
+ continue;
7109
+ if (tool.tool_id !== "send_whatsapp_message")
7110
+ continue;
7111
+ const settings = tool.provider_settings;
7112
+ if (!settings || typeof settings !== "object")
7113
+ continue;
7114
+ const templates = settings.templates;
7115
+ if (templates === void 0)
7116
+ continue;
7117
+ if (!Array.isArray(templates)) {
7118
+ errors.push("send_whatsapp_message: provider_settings.templates must be an array");
7119
+ continue;
7120
+ }
7121
+ for (let i = 0; i < templates.length; i++) {
7122
+ const entry = templates[i];
7123
+ const parsed = boundTemplateEntrySchema.safeParse(entry);
7124
+ if (!parsed.success) {
7125
+ const keyName = entry && typeof entry === "object" && entry.key ? String(entry.key) : `index_${i}`;
7126
+ for (const issue of parsed.error.issues) {
7127
+ const pathStr = issue.path.length > 0 ? issue.path.join(".") : "root";
7128
+ errors.push(`send_whatsapp_message template "${keyName}": ${pathStr}: ${issue.message}`);
7129
+ }
7130
+ }
7131
+ }
7132
+ }
7133
+ return errors;
7134
+ }
7135
+ var import_zod, SUPPORTED_WHATSAPP_COUNTRIES, slotSourceSchema, slotSchema, buttonTypeSchema, buttonSchema, basePolicySchema, boundPolicySchema, baseEntryShape, templateEntrySchema, boundTemplateEntrySchema;
7136
+ var init_whatsappTemplates = __esm({
7137
+ "../shared-types/dist/whatsappTemplates.js"() {
7138
+ "use strict";
7139
+ import_zod = require("zod");
7140
+ init_supportedCountries();
7141
+ SUPPORTED_WHATSAPP_COUNTRIES = SUPPORTED_COUNTRY_CODES;
7142
+ slotSourceSchema = import_zod.z.enum([
7143
+ "fixed",
7144
+ "agent_field",
7145
+ "captured",
7146
+ "call",
7147
+ "model"
7148
+ ]);
7149
+ slotSchema = import_zod.z.object({
7150
+ source: slotSourceSchema,
7151
+ path: import_zod.z.string().optional(),
7152
+ value: import_zod.z.string().optional()
7153
+ });
7154
+ buttonTypeSchema = import_zod.z.enum(["url", "quick_reply"]);
7155
+ buttonSchema = import_zod.z.object({
7156
+ index: import_zod.z.number().int().min(0),
7157
+ type: buttonTypeSchema,
7158
+ source: slotSourceSchema.optional(),
7159
+ path: import_zod.z.string().optional(),
7160
+ value: import_zod.z.string().optional(),
7161
+ payload: import_zod.z.string().optional(),
7162
+ reply: import_zod.z.record(import_zod.z.string()).optional()
7163
+ });
7164
+ basePolicySchema = import_zod.z.object({
7165
+ once_per_number: import_zod.z.boolean(),
7166
+ daily_cap: import_zod.z.number().int().min(1).max(3).optional(),
7167
+ allowed_countries: import_zod.z.array(import_zod.z.string()).optional(),
7168
+ max_per_call: import_zod.z.number().int().min(1).optional(),
7169
+ recipient: import_zod.z.enum(["caller_phone", "spoken_confirmed"]).optional(),
7170
+ offer: import_zod.z.enum(["before_goodbye", "on_request"]).optional(),
7171
+ offer_instruction: import_zod.z.string().min(1).optional()
7172
+ });
7173
+ boundPolicySchema = basePolicySchema.extend({
7174
+ max_per_call: import_zod.z.number().int().min(1),
7175
+ recipient: import_zod.z.enum(["caller_phone", "spoken_confirmed"]),
7176
+ offer: import_zod.z.enum(["before_goodbye", "on_request"]),
7177
+ offer_instruction: import_zod.z.string().min(1)
7178
+ });
7179
+ baseEntryShape = {
7180
+ key: import_zod.z.string().min(1),
7181
+ label: import_zod.z.string().min(1),
7182
+ languages: import_zod.z.record(import_zod.z.string().min(1)),
7183
+ variables: import_zod.z.array(slotSchema),
7184
+ buttons: import_zod.z.array(buttonSchema).optional()
7185
+ };
7186
+ templateEntrySchema = import_zod.z.object({
7187
+ ...baseEntryShape,
7188
+ policy: basePolicySchema
7189
+ }).superRefine((data, ctx) => {
7190
+ if (data.key !== "free_form" && hasModelSlot(data)) {
7191
+ ctx.addIssue({
7192
+ code: import_zod.z.ZodIssueCode.custom,
7193
+ message: "model slot is only allowed on the free_form entry",
7194
+ path: ["variables"]
7195
+ });
7196
+ }
7197
+ });
7198
+ boundTemplateEntrySchema = import_zod.z.object({
7199
+ ...baseEntryShape,
7200
+ policy: boundPolicySchema
7201
+ }).superRefine((data, ctx) => {
7202
+ if (data.key !== "free_form" && hasModelSlot(data)) {
7203
+ ctx.addIssue({
7204
+ code: import_zod.z.ZodIssueCode.custom,
7205
+ message: "model slot is only allowed on the free_form entry",
7206
+ path: ["variables"]
7207
+ });
7208
+ }
7209
+ });
7210
+ }
7211
+ });
7212
+
6951
7213
  // ../shared-types/dist/index.js
6952
7214
  var dist_exports = {};
6953
7215
  __export(dist_exports, {
@@ -7013,6 +7275,7 @@ __export(dist_exports, {
7013
7275
  STUDIO_SUPPORTED_LANGUAGES: () => STUDIO_SUPPORTED_LANGUAGES,
7014
7276
  SUPPORTED_COUNTRIES: () => SUPPORTED_COUNTRIES,
7015
7277
  SUPPORTED_COUNTRY_CODES: () => SUPPORTED_COUNTRY_CODES,
7278
+ SUPPORTED_WHATSAPP_COUNTRIES: () => SUPPORTED_WHATSAPP_COUNTRIES,
7016
7279
  SYSTEM_VARIABLES: () => SYSTEM_VARIABLES,
7017
7280
  SYSTEM_VARIABLE_KEYS: () => SYSTEM_VARIABLE_KEYS,
7018
7281
  TRACE_ID_HEADER: () => TRACE_ID_HEADER,
@@ -7025,9 +7288,15 @@ __export(dist_exports, {
7025
7288
  applyFlatDiff: () => applyFlatDiff,
7026
7289
  applyWritesToConfig: () => applyWritesToConfig,
7027
7290
  assertE164: () => assertE164,
7291
+ basePolicySchema: () => basePolicySchema,
7292
+ boundPolicySchema: () => boundPolicySchema,
7293
+ boundTemplateEntrySchema: () => boundTemplateEntrySchema,
7294
+ buildComponents: () => buildComponents,
7028
7295
  buildPlans: () => buildPlans,
7029
7296
  buildSystemBusinessValues: () => buildSystemBusinessValues,
7030
7297
  buildTranscriptText: () => buildTranscriptText,
7298
+ buttonSchema: () => buttonSchema,
7299
+ buttonTypeSchema: () => buttonTypeSchema,
7031
7300
  canonicalizeLlmProvider: () => canonicalizeLlmProvider,
7032
7301
  changedFocusedStudioSections: () => changedFocusedStudioSections,
7033
7302
  clarifyableKeys: () => clarifyableKeys,
@@ -7063,6 +7332,7 @@ __export(dist_exports, {
7063
7332
  inferCallerMetadataKey: () => inferCallerMetadataKey2,
7064
7333
  isAgentToolEnabled: () => isAgentToolEnabled,
7065
7334
  isApiKeyScope: () => isApiKeyScope,
7335
+ isCountryAllowed: () => isCountryAllowed,
7066
7336
  isCuratedBusinessType: () => isCuratedBusinessType,
7067
7337
  isDemoDialableCountry: () => isDemoDialableCountry,
7068
7338
  isE164: () => isE164,
@@ -7077,6 +7347,7 @@ __export(dist_exports, {
7077
7347
  isValidTraceId: () => isValidTraceId,
7078
7348
  isVoicemailEndReason: () => isVoicemailEndReason,
7079
7349
  isWithinCallingWindow: () => isWithinCallingWindow,
7350
+ langCode: () => langCode,
7080
7351
  listActiveConnectors: () => listActiveConnectors,
7081
7352
  listContextFields: () => listContextFields,
7082
7353
  mergePostCallConfig: () => mergePostCallConfig,
@@ -7088,10 +7359,12 @@ __export(dist_exports, {
7088
7359
  normalizeVariableAcquisition: () => normalizeVariableAcquisition2,
7089
7360
  phoneNumberCountry: () => phoneNumberCountry,
7090
7361
  phoneNumberIssue: () => phoneNumberIssue,
7362
+ pickSyncedTemplate: () => pickSyncedTemplate,
7091
7363
  pollUntil: () => pollUntil,
7092
7364
  populatedFocusedStudioSections: () => populatedFocusedStudioSections,
7093
7365
  pronunciationSupport: () => pronunciationSupport,
7094
7366
  providerIdsForTool: () => providerIdsForTool,
7367
+ providerRequiresExplicitVoice: () => providerRequiresExplicitVoice,
7095
7368
  publishRequiredKeys: () => publishRequiredKeys,
7096
7369
  readFocusedSectionField: () => readFocusedSectionField,
7097
7370
  readFromPayload: () => readFromPayload,
@@ -7100,6 +7373,7 @@ __export(dist_exports, {
7100
7373
  reinitKeys: () => reinitKeys,
7101
7374
  renderFieldReference: () => renderFieldReference,
7102
7375
  requiredConsentChannels: () => requiredConsentChannels,
7376
+ resolveLangTag: () => resolveLangTag,
7103
7377
  resolveManagedPricePerMin: () => resolveManagedPricePerMin,
7104
7378
  resolveSystemAlias: () => resolveSystemAlias,
7105
7379
  sanitizeTranscriptText: () => sanitizeTranscriptText,
@@ -7107,13 +7381,20 @@ __export(dist_exports, {
7107
7381
  serializeSection: () => serializeSection,
7108
7382
  skuAllowsCountry: () => skuAllowsCountry,
7109
7383
  skuFeaturedInCountry: () => skuFeaturedInCountry,
7384
+ slotSchema: () => slotSchema,
7385
+ slotSourceSchema: () => slotSourceSchema,
7110
7386
  stackCostPerMin: () => stackCostPerMin,
7111
7387
  supportedCountry: () => supportedCountry,
7388
+ templateEntrySchema: () => templateEntrySchema,
7389
+ templateShapeError: () => templateShapeError,
7112
7390
  toSupportedE164: () => toSupportedE164,
7113
7391
  toToolCapabilitySafeView: () => toToolCapabilitySafeView,
7114
7392
  validateAgentTemplate: () => validateAgentTemplate,
7115
7393
  validatePublishConfig: () => validatePublishConfig,
7394
+ valueRuleError: () => valueRuleError,
7116
7395
  variablesFromRequiredSlots: () => variablesFromRequiredSlots2,
7396
+ whatsappSenderId: () => whatsappSenderId,
7397
+ whatsappTemplateBindingErrors: () => whatsappTemplateBindingErrors,
7117
7398
  writeToPayload: () => writeToPayload
7118
7399
  });
7119
7400
  var deriveExtractionFields2, deriveRequiredSlots2, humanizeKey2, inferCallerMetadataKey2, normalizeVariableAcquisition2, normalizeKey2, registerVariable2, variablesFromRequiredSlots2;
@@ -7163,6 +7444,7 @@ var init_dist2 = __esm({
7163
7444
  init_safeUrl();
7164
7445
  init_connectorCatalog();
7165
7446
  init_supportedCountries();
7447
+ init_whatsappTemplates();
7166
7448
  deriveExtractionFields2 = deriveExtractionFields;
7167
7449
  deriveRequiredSlots2 = deriveRequiredSlots;
7168
7450
  humanizeKey2 = humanizeKey;
@@ -7202,6 +7484,7 @@ var require_dist = __commonJS({
7202
7484
  keyAllowsTool: () => keyAllowsTool2,
7203
7485
  opsToolCatalog: () => opsToolCatalog2,
7204
7486
  resolveToolDisposition: () => resolveToolDisposition,
7487
+ toolAnnotations: () => toolAnnotations2,
7205
7488
  withWorkspaceParam: () => withWorkspaceParam2
7206
7489
  });
7207
7490
  module2.exports = __toCommonJS2(index_exports);
@@ -7220,7 +7503,7 @@ var require_dist = __commonJS({
7220
7503
  if (p.scope === "account" && !PRIVILEGED.has(p.role)) return "deny";
7221
7504
  return p.risk === "write" ? "propose" : "confirm";
7222
7505
  }
7223
- var import_zod = require("zod");
7506
+ var import_zod2 = require("zod");
7224
7507
  var import_shared_types = (init_dist2(), __toCommonJS(dist_exports));
7225
7508
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7226
7509
  var norm2 = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
@@ -7237,32 +7520,32 @@ var require_dist = __commonJS({
7237
7520
  throw new Error(`No agent named "${raw}" found \u2014 call list_agents to get a valid agent UUID.`);
7238
7521
  }
7239
7522
  var agentConfigFields = {
7240
- system_prompt: import_zod.z.string().optional().describe("Full system prompt for the agent. If given without persona/playbook, the server auto-structures it."),
7241
- voice: import_zod.z.string().optional().describe('Voice ID (e.g. "Aoede", "Charon"). Call list_llm_options for valid values. Leave empty for realtime LLMs and Deepgram TTS, which carry their own voice.'),
7242
- language: import_zod.z.string().optional().describe('Primary BCP-47 language tag (e.g. "hi-IN", "en-US").'),
7243
- supported_languages: import_zod.z.array(import_zod.z.string()).optional().describe('All BCP-47 languages the agent should handle, e.g. ["hi-IN","en-US"] for a bilingual agent. The primary `language` is added automatically if omitted here.'),
7244
- llm_provider: import_zod.z.enum(import_shared_types.AGENT_LLM_PROVIDERS).optional(),
7245
- llm_model: import_zod.z.string().optional().describe('LLM model id from list_llm_options (e.g. "gemini-2.5-flash", "sarvam-105b").'),
7246
- llm_fallback_provider: import_zod.z.string().nullable().optional().describe("Fallback LLM provider; null clears it."),
7247
- llm_fallback_model: import_zod.z.string().nullable().optional().describe("Fallback LLM model; null clears it."),
7248
- stt_provider: import_zod.z.string().optional().describe('Speech-to-text provider (e.g. "deepgram", "sarvam").'),
7249
- stt_model: import_zod.z.string().optional(),
7250
- stt_fallback_provider: import_zod.z.string().nullable().optional(),
7251
- stt_fallback_model: import_zod.z.string().nullable().optional(),
7252
- tts_provider: import_zod.z.string().optional().describe('Text-to-speech provider (e.g. "elevenlabs", "sarvam", "cartesia").'),
7253
- tts_model: import_zod.z.string().optional(),
7254
- tts_fallback_provider: import_zod.z.string().nullable().optional(),
7255
- tts_fallback_model: import_zod.z.string().nullable().optional(),
7256
- custom_llm_url: import_zod.z.string().nullable().optional().describe("Self-hosted LLM endpoint (https:// or wss://). Enterprise only; null clears."),
7257
- custom_voice_url: import_zod.z.string().nullable().optional().describe("Self-hosted TTS endpoint (https:// or wss://). Enterprise only; null clears."),
7258
- custom_voice_mode: import_zod.z.enum(["rymi", "openai-compat"]).optional().describe("Wire format for custom_voice_url."),
7259
- custom_transcriber_url: import_zod.z.string().nullable().optional().describe("Self-hosted STT endpoint (https:// or wss://). Enterprise only; null clears."),
7260
- prompt_mode: import_zod.z.enum(["builder", "raw"]).optional().describe('How the system prompt is interpreted: "builder" (server structures persona/playbook from system_prompt) or "raw" (use system_prompt verbatim \u2014 requires system_prompt). Defaults to "builder".'),
7261
- persona: import_zod.z.record(import_zod.z.any()).optional().describe("Persona object. persona.name is the name the agent speaks and introduces itself as (also shown on share/tester pages); it defaults to the label when omitted. Note: callerPersonas must be objects of shape {type, approach, detectedWhen}, NOT plain strings."),
7262
- playbook: import_zod.z.record(import_zod.z.any()).optional().describe("Playbook configuration object"),
7263
- advanced: import_zod.z.record(import_zod.z.any()).optional(),
7264
- features: import_zod.z.record(import_zod.z.any()).optional(),
7265
- post_call: import_zod.z.record(import_zod.z.any()).optional()
7523
+ system_prompt: import_zod2.z.string().optional().describe("Full system prompt for the agent. If given without persona/playbook, the server auto-structures it."),
7524
+ voice: import_zod2.z.string().optional().describe('Voice ID (e.g. "Aoede", "Charon"). Call list_llm_options for valid values. Leave empty for realtime LLMs and Deepgram TTS, which carry their own voice.'),
7525
+ language: import_zod2.z.string().optional().describe('Primary BCP-47 language tag (e.g. "hi-IN", "en-US"). For managed agents, must belong to the SKU\u2019s supported_languages.'),
7526
+ supported_languages: import_zod2.z.array(import_zod2.z.string()).optional().describe('All BCP-47 languages the agent should handle, e.g. ["hi-IN","en-US"] for a bilingual custom agent. Fixed to [language] by the plan for managed agents.'),
7527
+ llm_provider: import_zod2.z.enum(import_shared_types.AGENT_LLM_PROVIDERS).optional().describe("LLM provider (custom agents only; fixed by the plan for managed agents)."),
7528
+ llm_model: import_zod2.z.string().optional().describe('LLM model id from list_llm_options (e.g. "gemini-2.5-flash", "sarvam-105b"). Fixed by the plan for managed agents.'),
7529
+ llm_fallback_provider: import_zod2.z.string().nullable().optional().describe("Fallback LLM provider; null clears it. Fixed by the plan for managed agents."),
7530
+ llm_fallback_model: import_zod2.z.string().nullable().optional().describe("Fallback LLM model; null clears it. Fixed by the plan for managed agents."),
7531
+ stt_provider: import_zod2.z.string().optional().describe('Speech-to-text provider (e.g. "deepgram", "sarvam"). Fixed by the plan for managed agents.'),
7532
+ stt_model: import_zod2.z.string().optional().describe("Speech-to-text model id. Fixed by the plan for managed agents."),
7533
+ stt_fallback_provider: import_zod2.z.string().nullable().optional().describe("Fallback STT provider. Fixed by the plan for managed agents."),
7534
+ stt_fallback_model: import_zod2.z.string().nullable().optional().describe("Fallback STT model. Fixed by the plan for managed agents."),
7535
+ tts_provider: import_zod2.z.string().optional().describe('Text-to-speech provider (e.g. "elevenlabs", "sarvam", "cartesia"). Fixed by the plan for managed agents.'),
7536
+ tts_model: import_zod2.z.string().optional().describe("Text-to-speech model id. Fixed by the plan for managed agents."),
7537
+ tts_fallback_provider: import_zod2.z.string().nullable().optional().describe("Fallback TTS provider. Fixed by the plan for managed agents."),
7538
+ tts_fallback_model: import_zod2.z.string().nullable().optional().describe("Fallback TTS model. Fixed by the plan for managed agents."),
7539
+ custom_llm_url: import_zod2.z.string().nullable().optional().describe("Self-hosted LLM endpoint (https:// or wss://). Enterprise only; null clears."),
7540
+ custom_voice_url: import_zod2.z.string().nullable().optional().describe("Self-hosted TTS endpoint (https:// or wss://). Enterprise only; null clears."),
7541
+ custom_voice_mode: import_zod2.z.enum(["rymi", "openai-compat"]).optional().describe("Wire format for custom_voice_url."),
7542
+ custom_transcriber_url: import_zod2.z.string().nullable().optional().describe("Self-hosted STT endpoint (https:// or wss://). Enterprise only; null clears."),
7543
+ prompt_mode: import_zod2.z.enum(["builder", "raw"]).optional().describe('How the system prompt is interpreted: "builder" (server structures persona/playbook from system_prompt) or "raw" (use system_prompt verbatim \u2014 requires system_prompt). Defaults to "builder".'),
7544
+ persona: import_zod2.z.record(import_zod2.z.any()).optional().describe("Persona object. persona.name is the name the agent speaks and introduces itself as (also shown on share/tester pages); it defaults to the label when omitted. Note: callerPersonas must be objects of shape {type, approach, detectedWhen}, NOT plain strings."),
7545
+ playbook: import_zod2.z.record(import_zod2.z.any()).optional().describe("Playbook configuration object"),
7546
+ advanced: import_zod2.z.record(import_zod2.z.any()).optional(),
7547
+ features: import_zod2.z.record(import_zod2.z.any()).optional(),
7548
+ post_call: import_zod2.z.record(import_zod2.z.any()).optional()
7266
7549
  };
7267
7550
  function foldPromptMode(params) {
7268
7551
  const { prompt_mode, ...rest } = params;
@@ -7299,8 +7582,8 @@ var require_dist = __commonJS({
7299
7582
  routes: ["GET /v1/agents"],
7300
7583
  keyScopes: ["agents:read"],
7301
7584
  input: {
7302
- limit: import_zod.z.number().int().min(1).max(500).optional().describe("Max agents to return (default 50)"),
7303
- offset: import_zod.z.number().int().min(0).optional().describe("Pagination offset")
7585
+ limit: import_zod2.z.number().int().min(1).max(500).optional().describe("Max agents to return (default 50)"),
7586
+ offset: import_zod2.z.number().int().min(0).optional().describe("Pagination offset")
7304
7587
  },
7305
7588
  run: (client, { limit, offset }) => client.agents.list({ limit, offset })
7306
7589
  }),
@@ -7311,7 +7594,7 @@ var require_dist = __commonJS({
7311
7594
  risk: "read",
7312
7595
  routes: ["GET /v1/agents/:id"],
7313
7596
  keyScopes: ["agents:read"],
7314
- input: { agent_id: import_zod.z.string().uuid().describe("The agent UUID") },
7597
+ input: { agent_id: import_zod2.z.string().uuid().describe("The agent UUID") },
7315
7598
  run: (client, { agent_id }) => client.agents.retrieve(agent_id)
7316
7599
  }),
7317
7600
  defineTool({
@@ -7332,8 +7615,8 @@ var require_dist = __commonJS({
7332
7615
  routes: ["GET /v1/agents/llm-options"],
7333
7616
  keyScopes: ["agents:read"],
7334
7617
  input: {
7335
- provider: import_zod.z.string().optional().describe('Filter to one voice provider, e.g. "elevenlabs", "sarvam", "gemini", "cartesia", "deepgram".'),
7336
- model_id: import_zod.z.string().optional().describe("Filter to voices compatible with a given model id (matched against the voice's supported_model_ids).")
7618
+ provider: import_zod2.z.string().optional().describe('Filter to one voice provider, e.g. "elevenlabs", "sarvam", "gemini", "cartesia", "deepgram".'),
7619
+ model_id: import_zod2.z.string().optional().describe("Filter to voices compatible with a given model id (matched against the voice's supported_model_ids).")
7337
7620
  },
7338
7621
  run: async (client, { provider, model_id }) => {
7339
7622
  const { voices } = await client.agents.llmOptions();
@@ -7366,9 +7649,9 @@ var require_dist = __commonJS({
7366
7649
  routes: ["POST /v1/agents/stack-preview"],
7367
7650
  keyScopes: ["agents:write"],
7368
7651
  input: {
7369
- supported_languages: import_zod.z.array(import_zod.z.string()).min(1).describe('BCP-47 languages to resolve a stack for, e.g. ["hi-IN","en-US"].'),
7370
- language: import_zod.z.string().optional().describe("Primary BCP-47 language (defaults to the first supported language)."),
7371
- current_provider_config: import_zod.z.record(import_zod.z.any()).optional().describe("Existing provider_config to diff against, if any.")
7652
+ supported_languages: import_zod2.z.array(import_zod2.z.string()).min(1).describe('BCP-47 languages to resolve a stack for, e.g. ["hi-IN","en-US"].'),
7653
+ language: import_zod2.z.string().optional().describe("Primary BCP-47 language (defaults to the first supported language)."),
7654
+ current_provider_config: import_zod2.z.record(import_zod2.z.any()).optional().describe("Existing provider_config to diff against, if any.")
7372
7655
  },
7373
7656
  run: (client, params) => client.agents.previewStack(params)
7374
7657
  }),
@@ -7380,10 +7663,10 @@ var require_dist = __commonJS({
7380
7663
  routes: ["GET /v1/agents/:id/calls"],
7381
7664
  keyScopes: ["agents:read"],
7382
7665
  input: {
7383
- agent_id: import_zod.z.string().uuid(),
7384
- limit: import_zod.z.number().int().min(1).max(200).optional(),
7385
- offset: import_zod.z.number().int().min(0).optional(),
7386
- status: import_zod.z.string().optional().describe("Filter by call status")
7666
+ agent_id: import_zod2.z.string().uuid(),
7667
+ limit: import_zod2.z.number().int().min(1).max(200).optional(),
7668
+ offset: import_zod2.z.number().int().min(0).optional(),
7669
+ status: import_zod2.z.string().optional().describe("Filter by call status")
7387
7670
  },
7388
7671
  run: (client, { agent_id, ...params }) => client.agents.listCalls(agent_id, params)
7389
7672
  }),
@@ -7395,11 +7678,11 @@ var require_dist = __commonJS({
7395
7678
  routes: ["POST /v1/agents/validate-publish"],
7396
7679
  keyScopes: ["agents:write"],
7397
7680
  input: {
7398
- agent_id: import_zod.z.string().uuid().optional().describe("Merge validation with a persisted agent"),
7399
- name: import_zod.z.string().optional(),
7400
- voice: import_zod.z.string().optional(),
7401
- persona: import_zod.z.record(import_zod.z.any()).optional(),
7402
- playbook: import_zod.z.record(import_zod.z.any()).optional()
7681
+ agent_id: import_zod2.z.string().uuid().optional().describe("Merge validation with a persisted agent"),
7682
+ name: import_zod2.z.string().optional(),
7683
+ voice: import_zod2.z.string().optional(),
7684
+ persona: import_zod2.z.record(import_zod2.z.any()).optional(),
7685
+ playbook: import_zod2.z.record(import_zod2.z.any()).optional()
7403
7686
  },
7404
7687
  run: (client, params) => client.agents.validatePublish(params)
7405
7688
  }),
@@ -7411,10 +7694,10 @@ var require_dist = __commonJS({
7411
7694
  routes: ["GET /v1/agents/:id", "POST /v1/agents/apply-changes"],
7412
7695
  keyScopes: ["agents:read", "agents:write"],
7413
7696
  input: {
7414
- agent_id: import_zod.z.string().uuid().describe("Agent to load currentConfig from (recommended)"),
7415
- changes: import_zod.z.array(import_zod.z.object({ key: import_zod.z.string(), value: import_zod.z.any() })).describe("Array of {key, value} field changes"),
7416
- mode: import_zod.z.enum(["create", "edit"]).describe("create = new agent, edit = updating existing"),
7417
- lenient: import_zod.z.boolean().optional().describe("Skip unknown-field hard-fail (not recommended)")
7697
+ agent_id: import_zod2.z.string().uuid().describe("Agent to load currentConfig from (recommended)"),
7698
+ changes: import_zod2.z.array(import_zod2.z.object({ key: import_zod2.z.string(), value: import_zod2.z.any() })).describe("Array of {key, value} field changes"),
7699
+ mode: import_zod2.z.enum(["create", "edit"]).describe("create = new agent, edit = updating existing"),
7700
+ lenient: import_zod2.z.boolean().optional().describe("Skip unknown-field hard-fail (not recommended)")
7418
7701
  },
7419
7702
  run: async (client, { agent_id, changes, mode, lenient }) => {
7420
7703
  const current = await client.agents.retrieve(agent_id);
@@ -7435,8 +7718,8 @@ var require_dist = __commonJS({
7435
7718
  routes: ["POST /v1/agents/enrich-company"],
7436
7719
  keyScopes: ["agents:write"],
7437
7720
  input: {
7438
- company_name: import_zod.z.string().min(1),
7439
- website_url: import_zod.z.string().url()
7721
+ company_name: import_zod2.z.string().min(1),
7722
+ website_url: import_zod2.z.string().url()
7440
7723
  },
7441
7724
  run: (client, { company_name, website_url }) => client.agents.enrichCompany({ companyName: company_name, websiteUrl: website_url })
7442
7725
  }),
@@ -7448,10 +7731,10 @@ var require_dist = __commonJS({
7448
7731
  routes: ["POST /v1/agents/generate"],
7449
7732
  keyScopes: ["agents:write"],
7450
7733
  input: {
7451
- prompt: import_zod.z.string().min(1).describe("Description of the agent you want to create"),
7452
- mode: import_zod.z.enum(["create", "edit"]).optional().default("create"),
7453
- current_config: import_zod.z.record(import_zod.z.any()).optional().describe("Existing config when editing"),
7454
- options: import_zod.z.record(import_zod.z.any()).optional().describe("Override hints e.g. {voice, llm_provider}")
7734
+ prompt: import_zod2.z.string().min(1).describe("Description of the agent you want to create"),
7735
+ mode: import_zod2.z.enum(["create", "edit"]).optional().default("create"),
7736
+ current_config: import_zod2.z.record(import_zod2.z.any()).optional().describe("Existing config when editing"),
7737
+ options: import_zod2.z.record(import_zod2.z.any()).optional().describe("Override hints e.g. {voice, llm_provider}")
7455
7738
  },
7456
7739
  run: (client, params) => client.agents.generate({ prompt: params.prompt, options: params.options })
7457
7740
  }),
@@ -7463,7 +7746,7 @@ var require_dist = __commonJS({
7463
7746
  routes: ["POST /v1/agents"],
7464
7747
  keyScopes: ["agents:write"],
7465
7748
  input: {
7466
- name: import_zod.z.string().min(1).describe("Studio label: the name shown in the sidebar/agent list only. The name the agent speaks is persona.name."),
7749
+ name: import_zod2.z.string().min(1).describe("Studio label: the name shown in the sidebar/agent list only. The name the agent speaks is persona.name."),
7467
7750
  ...agentConfigFields
7468
7751
  },
7469
7752
  run: (client, params) => client.agents.create(normalizeLlmProvider(foldPromptMode(params)))
@@ -7476,10 +7759,10 @@ var require_dist = __commonJS({
7476
7759
  routes: ["GET /v1/agents", "PUT /v1/agents/:id"],
7477
7760
  keyScopes: ["agents:read", "agents:write"],
7478
7761
  input: {
7479
- agent_id: import_zod.z.string().uuid().describe("The agent UUID to update"),
7480
- name: import_zod.z.string().optional().describe("Studio label (sidebar/agent list only). To change the spoken name, set persona.name."),
7762
+ agent_id: import_zod2.z.string().uuid().describe("The agent UUID to update"),
7763
+ name: import_zod2.z.string().optional().describe("Studio label (sidebar/agent list only). To change the spoken name, set persona.name."),
7481
7764
  ...agentConfigFields,
7482
- chat_summary: import_zod.z.string().nullable().optional()
7765
+ chat_summary: import_zod2.z.string().nullable().optional()
7483
7766
  },
7484
7767
  run: async (client, { agent_id, ...params }) => client.agents.update(await resolveAgentId(client, agent_id), normalizeLlmProvider(foldPromptMode(params)))
7485
7768
  }),
@@ -7490,7 +7773,7 @@ var require_dist = __commonJS({
7490
7773
  risk: "sensitive",
7491
7774
  routes: ["GET /v1/agents", "DELETE /v1/agents/:id"],
7492
7775
  keyScopes: ["agents:read", "agents:write"],
7493
- input: { agent_id: import_zod.z.string().uuid().describe("The agent UUID to delete") },
7776
+ input: { agent_id: import_zod2.z.string().uuid().describe("The agent UUID to delete") },
7494
7777
  run: async (client, { agent_id }) => client.agents.delete(await resolveAgentId(client, agent_id))
7495
7778
  }),
7496
7779
  defineTool({
@@ -7500,11 +7783,11 @@ var require_dist = __commonJS({
7500
7783
  risk: "write",
7501
7784
  routes: ["GET /v1/agents", "POST /v1/agents/:id/clone"],
7502
7785
  keyScopes: ["agents:read", "agents:write"],
7503
- input: { agent_id: import_zod.z.string().uuid().describe("The agent UUID to clone") },
7786
+ input: { agent_id: import_zod2.z.string().uuid().describe("The agent UUID to clone") },
7504
7787
  run: async (client, { agent_id }) => client.agents.clone(await resolveAgentId(client, agent_id))
7505
7788
  })
7506
7789
  ];
7507
- var import_zod2 = require("zod");
7790
+ var import_zod22 = require("zod");
7508
7791
  var callTools = [
7509
7792
  defineTool({
7510
7793
  name: "list_calls",
@@ -7514,10 +7797,10 @@ var require_dist = __commonJS({
7514
7797
  routes: ["GET /v1/calls"],
7515
7798
  keyScopes: ["calls:read"],
7516
7799
  input: {
7517
- limit: import_zod2.z.number().int().min(1).max(200).optional().describe("Max calls to return"),
7518
- offset: import_zod2.z.number().int().min(0).optional().describe("Pagination offset"),
7519
- cursor: import_zod2.z.string().optional().describe("Opaque cursor for keyset pagination"),
7520
- status: import_zod2.z.string().optional().describe("Filter by call status (e.g. completed, in_progress, failed)")
7800
+ limit: import_zod22.z.number().int().min(1).max(200).optional().describe("Max calls to return"),
7801
+ offset: import_zod22.z.number().int().min(0).optional().describe("Pagination offset"),
7802
+ cursor: import_zod22.z.string().optional().describe("Opaque cursor for keyset pagination"),
7803
+ status: import_zod22.z.string().optional().describe("Filter by call status (e.g. completed, in_progress, failed)")
7521
7804
  },
7522
7805
  run: (client, params) => client.calls.list(params)
7523
7806
  }),
@@ -7529,8 +7812,8 @@ var require_dist = __commonJS({
7529
7812
  routes: ["GET /v1/calls/active"],
7530
7813
  keyScopes: ["calls:read"],
7531
7814
  input: {
7532
- limit: import_zod2.z.number().int().min(1).max(200).optional(),
7533
- offset: import_zod2.z.number().int().min(0).optional()
7815
+ limit: import_zod22.z.number().int().min(1).max(200).optional(),
7816
+ offset: import_zod22.z.number().int().min(0).optional()
7534
7817
  },
7535
7818
  run: (client, params) => client.calls.active(params)
7536
7819
  }),
@@ -7541,7 +7824,7 @@ var require_dist = __commonJS({
7541
7824
  risk: "read",
7542
7825
  routes: ["GET /v1/calls/:id"],
7543
7826
  keyScopes: ["calls:read"],
7544
- input: { call_id: import_zod2.z.string().describe("The call ID") },
7827
+ input: { call_id: import_zod22.z.string().describe("The call ID") },
7545
7828
  run: (client, { call_id }) => client.calls.retrieve(call_id)
7546
7829
  }),
7547
7830
  defineTool({
@@ -7551,7 +7834,7 @@ var require_dist = __commonJS({
7551
7834
  risk: "read",
7552
7835
  routes: ["GET /v1/calls/:id/summary"],
7553
7836
  keyScopes: ["calls:read"],
7554
- input: { call_id: import_zod2.z.string().describe("The call ID") },
7837
+ input: { call_id: import_zod22.z.string().describe("The call ID") },
7555
7838
  run: (client, { call_id }) => client.calls.summary(call_id)
7556
7839
  }),
7557
7840
  defineTool({
@@ -7561,7 +7844,7 @@ var require_dist = __commonJS({
7561
7844
  risk: "read",
7562
7845
  routes: ["GET /v1/calls/:id/transcript"],
7563
7846
  keyScopes: ["calls:read"],
7564
- input: { call_id: import_zod2.z.string().describe("The call ID") },
7847
+ input: { call_id: import_zod22.z.string().describe("The call ID") },
7565
7848
  run: (client, { call_id }) => client.calls.transcript(call_id)
7566
7849
  }),
7567
7850
  defineTool({
@@ -7571,7 +7854,7 @@ var require_dist = __commonJS({
7571
7854
  risk: "read",
7572
7855
  routes: ["GET /v1/calls/:id/recording"],
7573
7856
  keyScopes: ["calls:read"],
7574
- input: { call_id: import_zod2.z.string().describe("The call ID") },
7857
+ input: { call_id: import_zod22.z.string().describe("The call ID") },
7575
7858
  run: (client, { call_id }) => client.calls.recording(call_id)
7576
7859
  }),
7577
7860
  defineTool({
@@ -7591,29 +7874,41 @@ var require_dist = __commonJS({
7591
7874
  risk: "write",
7592
7875
  routes: ["POST /v1/calls/:id/reprocess"],
7593
7876
  keyScopes: ["calls:write"],
7594
- input: { call_id: import_zod2.z.string().describe("The call ID to reprocess") },
7877
+ input: { call_id: import_zod22.z.string().describe("The call ID to reprocess") },
7595
7878
  run: (client, { call_id }) => client.calls.reprocess(call_id)
7596
7879
  }),
7597
7880
  defineTool({
7598
7881
  name: "create_call",
7599
- description: "WARNING: places a real, billable PSTN call. `from_number` is the caller ID shown to the recipient and must be a phone number registered to your account \u2014 omit it to use the agent's attached number. `identity` is the destination in strict E.164 (e.g. +15555550123).",
7882
+ description: "WARNING: places a real, billable PSTN call. `from_number` is the caller ID shown to the recipient and must be a phone number registered to your account \u2014 omit it to use the agent's attached number. `identity` is the destination in strict E.164 (e.g. +15555550123). Set `test` true to mark the call as a test and dial from the shared test number (no from_number; the destination must be a confirmed number).",
7600
7883
  scope: "agent",
7601
7884
  risk: "sensitive",
7602
7885
  routes: ["POST /v1/calls"],
7603
7886
  keyScopes: ["calls:write"],
7604
7887
  input: {
7605
- agent_id: import_zod2.z.string().uuid().describe("The agent that will handle the call"),
7606
- participants: import_zod2.z.array(import_zod2.z.object({
7607
- transport: import_zod2.z.enum(["webrtc", "pstn"]),
7608
- identity: import_zod2.z.string().describe("Destination phone number (pstn) or participant identity (webrtc)"),
7609
- from_number: import_zod2.z.string().optional().describe("Caller ID / from number for pstn"),
7610
- metadata: import_zod2.z.record(import_zod2.z.any()).optional()
7888
+ agent_id: import_zod22.z.string().uuid().describe("The agent that will handle the call"),
7889
+ participants: import_zod22.z.array(import_zod22.z.object({
7890
+ transport: import_zod22.z.enum(["webrtc", "pstn"]),
7891
+ identity: import_zod22.z.string().describe("Destination phone number (pstn) or participant identity (webrtc)"),
7892
+ from_number: import_zod22.z.string().optional().describe("Caller ID / from number for pstn"),
7893
+ metadata: import_zod22.z.record(import_zod22.z.any()).optional()
7611
7894
  })).min(1),
7612
- metadata: import_zod2.z.record(import_zod2.z.any()).optional(),
7613
- variables: import_zod2.z.record(import_zod2.z.any()).optional().describe("Playbook variables to seed the call"),
7614
- post_call: import_zod2.z.record(import_zod2.z.any()).optional()
7895
+ metadata: import_zod22.z.record(import_zod22.z.any()).optional(),
7896
+ variables: import_zod22.z.record(import_zod22.z.any()).optional().describe("Playbook variables to seed the call"),
7897
+ post_call: import_zod22.z.record(import_zod22.z.any()).optional(),
7898
+ test: import_zod22.z.boolean().optional().describe("Mark the call as a test and use the shared test number. Do not also set from_number.")
7615
7899
  },
7616
- run: (client, params) => client.calls.create(params)
7900
+ run: (client, params) => {
7901
+ const { test, metadata, ...rest } = params;
7902
+ if (test) {
7903
+ return client.calls.create({
7904
+ ...rest,
7905
+ test: true,
7906
+ use_test_pool: true,
7907
+ metadata: { ...metadata || {}, source: "mcp_test" }
7908
+ });
7909
+ }
7910
+ return client.calls.create({ ...rest, ...metadata ? { metadata } : {} });
7911
+ }
7617
7912
  }),
7618
7913
  defineTool({
7619
7914
  name: "batch_call",
@@ -7623,18 +7918,18 @@ var require_dist = __commonJS({
7623
7918
  routes: ["POST /v1/calls/batch"],
7624
7919
  keyScopes: ["calls:write"],
7625
7920
  input: {
7626
- agent_id: import_zod2.z.string().uuid().describe("The agent that will handle the calls"),
7627
- to: import_zod2.z.array(import_zod2.z.string()).optional().describe("Simple list of destination phone numbers"),
7628
- recipients: import_zod2.z.array(import_zod2.z.object({
7629
- to: import_zod2.z.string().optional(),
7630
- from_number: import_zod2.z.string().optional(),
7631
- metadata: import_zod2.z.record(import_zod2.z.any()).optional()
7921
+ agent_id: import_zod22.z.string().uuid().describe("The agent that will handle the calls"),
7922
+ to: import_zod22.z.array(import_zod22.z.string()).optional().describe("Simple list of destination phone numbers"),
7923
+ recipients: import_zod22.z.array(import_zod22.z.object({
7924
+ to: import_zod22.z.string().optional(),
7925
+ from_number: import_zod22.z.string().optional(),
7926
+ metadata: import_zod22.z.record(import_zod22.z.any()).optional()
7632
7927
  })).optional().describe("Per-recipient targets with optional from_number/metadata"),
7633
- from_number: import_zod2.z.string().optional().describe("Default caller ID / from number"),
7634
- batch_id: import_zod2.z.string().optional(),
7635
- metadata: import_zod2.z.record(import_zod2.z.any()).optional(),
7636
- variables: import_zod2.z.record(import_zod2.z.any()).optional(),
7637
- post_call: import_zod2.z.record(import_zod2.z.any()).optional()
7928
+ from_number: import_zod22.z.string().optional().describe("Default caller ID / from number"),
7929
+ batch_id: import_zod22.z.string().optional(),
7930
+ metadata: import_zod22.z.record(import_zod22.z.any()).optional(),
7931
+ variables: import_zod22.z.record(import_zod22.z.any()).optional(),
7932
+ post_call: import_zod22.z.record(import_zod22.z.any()).optional()
7638
7933
  },
7639
7934
  run: (client, params) => client.calls.batch(params)
7640
7935
  }),
@@ -7645,7 +7940,7 @@ var require_dist = __commonJS({
7645
7940
  risk: "sensitive",
7646
7941
  routes: ["POST /v1/calls/:id/end"],
7647
7942
  keyScopes: ["calls:write"],
7648
- input: { call_id: import_zod2.z.string().describe("The call ID to end") },
7943
+ input: { call_id: import_zod22.z.string().describe("The call ID to end") },
7649
7944
  run: (client, { call_id }) => client.calls.end(call_id)
7650
7945
  }),
7651
7946
  defineTool({
@@ -7656,12 +7951,12 @@ var require_dist = __commonJS({
7656
7951
  routes: ["POST /v1/calls/:id/participants"],
7657
7952
  keyScopes: ["calls:write"],
7658
7953
  input: {
7659
- call_id: import_zod2.z.string().describe("The in-progress call ID"),
7660
- participants: import_zod2.z.array(import_zod2.z.object({
7661
- transport: import_zod2.z.enum(["webrtc", "pstn"]),
7662
- identity: import_zod2.z.string().describe("Destination phone number (pstn, E.164) or participant identity (webrtc)"),
7663
- from_number: import_zod2.z.string().optional().describe("Caller ID for pstn"),
7664
- metadata: import_zod2.z.record(import_zod2.z.any()).optional()
7954
+ call_id: import_zod22.z.string().describe("The in-progress call ID"),
7955
+ participants: import_zod22.z.array(import_zod22.z.object({
7956
+ transport: import_zod22.z.enum(["webrtc", "pstn"]),
7957
+ identity: import_zod22.z.string().describe("Destination phone number (pstn, E.164) or participant identity (webrtc)"),
7958
+ from_number: import_zod22.z.string().optional().describe("Caller ID for pstn"),
7959
+ metadata: import_zod22.z.record(import_zod22.z.any()).optional()
7665
7960
  })).min(1)
7666
7961
  },
7667
7962
  run: (client, { call_id, participants }) => client.calls.addParticipants(call_id, { participants })
@@ -8982,6 +9277,39 @@ var require_dist = __commonJS({
8982
9277
  }
8983
9278
  };
8984
9279
  }
9280
+ var DESTRUCTIVE_NAMES = /* @__PURE__ */ new Set([
9281
+ "end_call",
9282
+ "undo_agent_change",
9283
+ "regenerate_share_link",
9284
+ "rotate_campaign_intake",
9285
+ // Overwrite or drop stored config through a PUT, so no DELETE route gives them away.
9286
+ "remove_agent_tool",
9287
+ "set_agent_tools",
9288
+ "set_tool_secret"
9289
+ ]);
9290
+ var IDEMPOTENT_NAMES = /* @__PURE__ */ new Set(["end_call", "pause_campaign"]);
9291
+ var NOT_IDEMPOTENT_NAMES = /* @__PURE__ */ new Set(["add_agent_tool"]);
9292
+ function isIdempotent(tool) {
9293
+ if (IDEMPOTENT_NAMES.has(tool.name)) return true;
9294
+ if (NOT_IDEMPOTENT_NAMES.has(tool.name)) return false;
9295
+ const writes = tool.routes.filter((r) => !r.startsWith("GET "));
9296
+ return writes.length > 0 && writes.every((r) => /^(PUT|PATCH|DELETE) /.test(r));
9297
+ }
9298
+ var ACRONYMS = { dnc: "DNC", llm: "LLM" };
9299
+ function titleOf(name) {
9300
+ const words = name.split("_").map((w) => ACRONYMS[w] ?? w);
9301
+ return words.join(" ").replace(/^./, (c) => c.toUpperCase());
9302
+ }
9303
+ function toolAnnotations2(tool) {
9304
+ const readOnly = tool.risk === "read";
9305
+ return {
9306
+ title: titleOf(tool.name),
9307
+ readOnlyHint: readOnly,
9308
+ destructiveHint: !readOnly && (DESTRUCTIVE_NAMES.has(tool.name) || tool.routes.some((r) => r.startsWith("DELETE "))),
9309
+ idempotentHint: readOnly || isIdempotent(tool),
9310
+ openWorldHint: !readOnly
9311
+ };
9312
+ }
8985
9313
  }
8986
9314
  });
8987
9315
 
@@ -9011,7 +9339,8 @@ function withToolErrors(handler) {
9011
9339
  // package.json
9012
9340
  var package_default = {
9013
9341
  name: "@rymi/mcp",
9014
- version: "2.8.2",
9342
+ mcpName: "io.github.rymi-live/rymi-mcp",
9343
+ version: "2.10.0",
9015
9344
  description: "Rymi MCP server \u2014 manage AI voice agents via Model Context Protocol",
9016
9345
  license: "MIT",
9017
9346
  author: "Rymi AI <engineering@rymi.live>",
@@ -9107,6 +9436,7 @@ async function createServer(apiKey2, options = {}) {
9107
9436
  tool.name,
9108
9437
  tool.description,
9109
9438
  tool.input,
9439
+ (0, import_ops_tools.toolAnnotations)(tool),
9110
9440
  withToolErrors(async (params) => {
9111
9441
  const result2 = await tool.run(rymi, params);
9112
9442
  return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@rymi/mcp",
3
- "version": "2.8.2",
3
+ "mcpName": "io.github.rymi-live/rymi-mcp",
4
+ "version": "2.10.0",
4
5
  "description": "Rymi MCP server — manage AI voice agents via Model Context Protocol",
5
6
  "license": "MIT",
6
7
  "author": "Rymi AI <engineering@rymi.live>",
@@ -44,7 +45,7 @@
44
45
  },
45
46
  "dependencies": {
46
47
  "@modelcontextprotocol/sdk": "^1.11.1",
47
- "@rymi/node": "^2.7.2",
48
+ "@rymi/node": "^2.8.0",
48
49
  "zod": "^3.23.0"
49
50
  },
50
51
  "devDependencies": {