@velaro/mcp-server 0.6.75 → 0.6.77

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/README.md +6 -0
  2. package/package.json +1 -1
  3. package/server.js +19 -0
package/README.md CHANGED
@@ -119,6 +119,12 @@ This works with any MCP client that supports HTTP/SSE transport — including Cl
119
119
  | `bot_get` | Get full bot config including system prompt |
120
120
  | `bot_update_prompt` | Update a bot's system prompt |
121
121
 
122
+ ### CRM Mobile Fields
123
+ | Tool | What It Does |
124
+ |------|-------------|
125
+ | `crm_mobile_fields_get` | Show which CRM fields the mobile app displays for NetSuite, Dynamics, Salesforce or HubSpot (mode, custom list, inherited info-panel list) |
126
+ | `crm_mobile_fields_set` | Set the mode (inherit or custom) and the ordered custom field list; validated and audit-logged. Dynamics and HubSpot require the plan that includes them |
127
+
122
128
  ### Contacts
123
129
  | Tool | What It Does |
124
130
  |------|-------------|
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velaro/mcp-server",
3
- "version": "0.6.75",
3
+ "version": "0.6.77",
4
4
  "description": "Velaro MCP server — connect Claude and other AI agents directly to your Velaro account: KB, workflows, bots, conversations, contacts, routing, and more.",
5
5
  "type": "module",
6
6
  "bin": {
package/server.js CHANGED
@@ -300,6 +300,7 @@ const MESSAGING_ADMIN_TOOLS = new Set([
300
300
  'workflow_create', 'workflow_list', 'workflow_get', 'workflow_toggle',
301
301
  'bot_create', 'bot_list', 'bot_get', 'bot_update_prompt', 'bot_set_knowledge',
302
302
  'ai_config_attach_index', 'call_pop_settings_get', 'call_pop_settings_set',
303
+ 'crm_mobile_fields_get', 'crm_mobile_fields_set',
303
304
  'agent_list', 'team_list', 'conversation_list', 'conversation_get', 'conversation_search',
304
305
  'contact_search', 'contact_get', 'routing_list', 'routing_get', 'site_info',
305
306
  'ms_bookings_cancel_appointment', 'ms_bookings_check_availability_range', 'ms_bookings_reschedule_appointment',
@@ -4150,6 +4151,7 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
4150
4151
  description: { type: 'string', description: 'New description' },
4151
4152
  contactSales: { type: 'boolean', description: 'Set true to hide price and show "Contact sales"' },
4152
4153
  isActive: { type: 'boolean', description: 'Set false to deactivate (hide from catalog)' },
4154
+ limits: { type: 'object', description: 'Plan limit keys merged into MetadataJson (numbers): aiTokensPerMonth, includedMcpCalls, apiCallsPerMonth, webhookInvocationsPerMonth, httpActionsPerMonth, emailSendsPerMonth, blobUploadMbPerMonth. Other keys are preserved.' },
4153
4155
  },
4154
4156
  required: ['packageKey'],
4155
4157
  },
@@ -9280,6 +9282,13 @@ async function handleTool(name, args) {
9280
9282
  for (const p of items) {
9281
9283
  const price = p.contactSales ? 'Contact sales' : (p.monthlyPriceCents ? `$${(p.monthlyPriceCents/100).toFixed(0)}${p.unitLabel||'/mo'}` : 'Free');
9282
9284
  lines.push(` ${p.packageKey.padEnd(40)} ${price.padEnd(18)} v${p.version} ${p.displayName}`);
9285
+ if (p.packageType === 'plan' && p.metadataJson) {
9286
+ try {
9287
+ const m = JSON.parse(p.metadataJson);
9288
+ const lim = ['aiTokensPerMonth','includedMcpCalls','apiCallsPerMonth','webhookInvocationsPerMonth','httpActionsPerMonth','emailSendsPerMonth','blobUploadMbPerMonth'].filter(k => m[k] != null).map(k => `${k}=${m[k]}`);
9289
+ if (lim.length) lines.push(` limits: ${lim.join(' ')}`);
9290
+ } catch { /* ignore bad metadata */ }
9291
+ }
9283
9292
  }
9284
9293
  }
9285
9294
  return lines.join('\n');
@@ -9294,6 +9303,16 @@ async function handleTool(name, args) {
9294
9303
  if (args.description) payload.description = args.description;
9295
9304
  if (args.contactSales != null) payload.contactSales = args.contactSales;
9296
9305
  if (args.isActive != null) payload.isActive = args.isActive;
9306
+ if (args.limits && typeof args.limits === 'object') {
9307
+ const LIMIT_KEYS = ['aiTokensPerMonth','includedMcpCalls','apiCallsPerMonth','webhookInvocationsPerMonth','httpActionsPerMonth','emailSendsPerMonth','blobUploadMbPerMonth'];
9308
+ const bad = Object.keys(args.limits).filter(k => !LIMIT_KEYS.includes(k));
9309
+ if (bad.length) throw new Error(`Unknown limit keys: ${bad.join(', ')}`);
9310
+ const all = await api('GET', '/Pricing/catalog');
9311
+ const cur = (Array.isArray(all) ? all : []).find(p => p.packageKey === args.packageKey);
9312
+ let meta = {};
9313
+ try { meta = cur?.metadataJson ? JSON.parse(cur.metadataJson) : {}; } catch { meta = {}; }
9314
+ payload.metadataJson = JSON.stringify({ ...meta, ...args.limits });
9315
+ }
9297
9316
  const result = await api('PUT', `/Pricing/catalog/${args.packageKey}`, payload);
9298
9317
  return `✅ Package '${result.packageKey}' updated to v${result.version}.`;
9299
9318
  }