@velaro/mcp-server 0.6.79 → 0.6.81

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 +1 -0
  2. package/package.json +1 -1
  3. package/server.js +129 -7
package/README.md CHANGED
@@ -118,6 +118,7 @@ This works with any MCP client that supports HTTP/SSE transport — including Cl
118
118
  | `bot_list` | List all bot/AI configurations for this site |
119
119
  | `bot_get` | Get full bot config including system prompt |
120
120
  | `bot_update_prompt` | Update a bot's system prompt |
121
+ | `ai_config_set_reply_format` | Set reply format: global (plain text), plain, or markdown |
121
122
 
122
123
  ### CRM Mobile Fields
123
124
  | Tool | What It Does |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velaro/mcp-server",
3
- "version": "0.6.79",
3
+ "version": "0.6.81",
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
@@ -299,7 +299,7 @@ async function gatewayInit() {
299
299
  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
- 'ai_config_attach_index', 'call_pop_settings_get', 'call_pop_settings_set',
302
+ 'ai_config_attach_index', 'ai_config_set_reply_format', 'call_pop_settings_get', 'call_pop_settings_set',
303
303
  'crm_mobile_fields_get', 'crm_mobile_fields_set',
304
304
  'agent_list', 'team_list', 'conversation_list', 'conversation_get', 'conversation_search',
305
305
  'contact_search', 'contact_get', 'routing_list', 'routing_get', 'site_info',
@@ -1165,6 +1165,18 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
1165
1165
  required: ['id', 'prompt'],
1166
1166
  },
1167
1167
  },
1168
+ {
1169
+ name: 'ai_config_set_reply_format',
1170
+ description: 'Set how a bot formats replies. mode: global (follow global default, plain text, no markdown, no em/en dashes), plain (force plain text), markdown (allow markdown; explicit bullet/table requests are honored). Applies to every channel. Admin UI: Bots > AI Settings > General > Reply format.',
1171
+ inputSchema: {
1172
+ type: 'object',
1173
+ properties: {
1174
+ aiConfigId: { type: 'number', description: 'AI configuration ID (from bot_list)' },
1175
+ mode: { type: 'string', enum: ['global', 'plain', 'markdown'], description: 'Reply format mode' },
1176
+ },
1177
+ required: ['aiConfigId', 'mode'],
1178
+ },
1179
+ },
1168
1180
  {
1169
1181
  name: 'site_identity_secret_status',
1170
1182
  description: 'Check whether a visitor identity signing secret is configured for this site. The secret lets pre-authenticated visitors (already logged in to the customer website) skip the OTP challenge when the bot looks up their CRM data. Returns whether configured and the masked secret. To generate or rotate the secret, the customer goes to Admin → Account Settings → Security → "Visitor Identity Signing Secret".',
@@ -1904,6 +1916,33 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
1904
1916
  required: ['indexName'],
1905
1917
  },
1906
1918
  },
1919
+ {
1920
+ name: 'kb_advise_knowledge_strategy',
1921
+ description: 'Recommend, per data source (manual_pdf, spec_sheet, policy_document, faq_or_help_pages, product_catalog, price_list, cross_reference_sheet, images_or_drawings, cad_files, other_documents), whether to embed all, embed some, use exact lookup or query live, exactly what to upload, and a rough size estimate. Pure computation: nothing is read or written. Estimates only. Wraps POST KnowledgeAdvisor/advise.',
1922
+ inputSchema: {
1923
+ type: 'object',
1924
+ properties: {
1925
+ sources: {
1926
+ type: 'array',
1927
+ items: {
1928
+ type: 'object',
1929
+ properties: {
1930
+ kind: { type: 'string' },
1931
+ name: { type: 'string' },
1932
+ pages: { type: 'integer' },
1933
+ rows: { type: 'integer' },
1934
+ changeFrequency: { type: 'string', description: 'static | monthly | weekly | daily | realtime' },
1935
+ hasExactIdentifiers: { type: 'boolean' },
1936
+ scanned: { type: 'boolean' },
1937
+ hasLiveSystem: { type: 'boolean' },
1938
+ },
1939
+ required: ['kind'],
1940
+ },
1941
+ },
1942
+ },
1943
+ required: ['sources'],
1944
+ },
1945
+ },
1907
1946
  {
1908
1947
  name: 'index_integrity_check',
1909
1948
  description: 'Read-only integrity report for a knowledge index: orphan chunks, records without chunks, count mismatches, duplicate records. Wraps GET IndexMove/Integrity.',
@@ -3651,6 +3690,51 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
3651
3690
  },
3652
3691
  },
3653
3692
 
3693
+ // ── Business actions + SAP (one definition, many surfaces) ─────────────────────
3694
+ {
3695
+ name: 'sap_diagnose',
3696
+ description: 'Run the SAP live diagnostic for a site: configuration completeness, authentication (real HTTP status) and, when deep, a per-capability read-only probe compared with what the capability matrix documents (S/4HANA on-prem/private/public, Business One, ECC via gateway). Never writes; a write capability is never reported as verified; secrets are never returned. Calls messaging GET diagnostics/test-sap?siteId=<id>&deep=<bool>. Velaro staff only.',
3697
+ inputSchema: {
3698
+ type: 'object',
3699
+ properties: {
3700
+ siteId: { type: 'number', description: 'Site to diagnose (e.g. 1032)' },
3701
+ deep: { type: 'boolean', description: 'Probe every capability (default true). false = configuration + authentication only.' },
3702
+ },
3703
+ required: ['siteId'],
3704
+ },
3705
+ },
3706
+ {
3707
+ name: 'business_action_list',
3708
+ description: 'List the shared business actions registered on the messaging API (e.g. get_customer_pricing, create_quote): name, whether it is a write, data class, freshness window, request JSON schema and the AI skill tool names that project it. One definition is served by the Velaro catalog or a connected ERP (SAP) beneath it. Site scope comes from the caller\'s auth context. Calls GET /BusinessActions.',
3709
+ inputSchema: { type: 'object', properties: {} },
3710
+ },
3711
+ {
3712
+ name: 'business_action_route',
3713
+ description: 'Deterministically route free text to the business action(s) it means (no model call, no side effects, grants nothing - authorization stays in the executor). Returns ranked matches with score, matched terms and AI skill tool names. Calls POST /BusinessActions/Route.',
3714
+ inputSchema: {
3715
+ type: 'object',
3716
+ properties: {
3717
+ text: { type: 'string', description: 'What the customer or agent asked for, e.g. "what is my contract price for BRG-6204"' },
3718
+ max: { type: 'number', description: 'Max matches (default 3)' },
3719
+ },
3720
+ required: ['text'],
3721
+ },
3722
+ },
3723
+ {
3724
+ name: 'business_action_execute',
3725
+ description: 'Execute a business action as the authenticated caller (agent actor; site from auth context, never from arguments). Read actions return data with source system and freshness; write actions are idempotent: repeating the same idempotencyKey (or the same body in the same conversation) returns the stored result and never creates a duplicate, a timed-out write reports OUTCOMEUNKNOWN and must be verified in the system of record before retrying. Prices are never accepted from the caller for ERP-priced actions. Calls POST /BusinessActions/{name}/Execute.',
3726
+ inputSchema: {
3727
+ type: 'object',
3728
+ properties: {
3729
+ name: { type: 'string', description: 'Action name from business_action_list, e.g. get_customer_pricing or create_quote' },
3730
+ request: { type: 'object', description: 'The action request body (see requestSchema from business_action_list)' },
3731
+ idempotencyKey: { type: 'string', description: 'For writes: reuse the same key to replay the same result instead of creating another document' },
3732
+ conversationId: { type: 'string', description: 'Optional conversation to attach the result to' },
3733
+ },
3734
+ required: ['name', 'request'],
3735
+ },
3736
+ },
3737
+
3654
3738
  // ── CallRail Attribution ──────────────────────────────────────────────────────
3655
3739
  {
3656
3740
  name: 'callrail_get_attributions',
@@ -4643,14 +4727,15 @@ For multiSelect dynamic options: the variable named in dynamicOptionsVariable mu
4643
4727
  },
4644
4728
  {
4645
4729
  name: 'recruiting_list_applications',
4646
- description: 'List candidate applications submitted via the Recruiting Bot for this site (name, email, phone, role interest, work authorization, availability, submitted timestamp).',
4730
+ description: 'List candidate applications submitted via the Recruiting Bot for this site (name, email, phone, role interest, work authorization, availability, submitted timestamp). Never contains EEOC self-ID data.',
4647
4731
  inputSchema: { type: 'object', properties: {}, required: [] },
4648
4732
  },
4649
4733
  // Recruiting/Applications/ExportEeoc (voluntary self-ID CSV export) is intentionally NOT
4650
- // exposed as an MCP tool -- it returns sensitive EEOC/OFCCP self-identification PII in bulk,
4651
- // and the existing admin-UI export link + `velaro recruiting applications export-eeoc` CLI
4652
- // command are the appropriate surfaces for a human-initiated compliance export, not an
4653
- // AI-reachable tool.
4734
+ // exposed as an MCP tool -- it returns sensitive EEOC/OFCCP self-identification PII in bulk.
4735
+ // It is administrator-only and audit-logged server-side (403 for ordinary agents); the
4736
+ // admin-UI export button (Administrators only) and `velaro recruiting applications
4737
+ // export-eeoc` CLI command are the appropriate surfaces for a human-initiated compliance
4738
+ // export, not an AI-reachable tool. EEOC data is never returned per application.
4654
4739
 
4655
4740
  // -- Multi-employer job board: named posting sources --
4656
4741
  // Requires EnableRecruitingBot + EnableJobBoardMultiEmployer. Same siteId-from-auth-context
@@ -5749,6 +5834,9 @@ async function handleTool(name, args) {
5749
5834
  case 'bot_update_prompt':
5750
5835
  return await rpc('bot_update_prompt', args);
5751
5836
 
5837
+ case 'ai_config_set_reply_format':
5838
+ return await rpc('ai_config_set_reply_format', args);
5839
+
5752
5840
  case 'site_identity_secret_status': {
5753
5841
  const settings = await api('GET', '/SiteSettings');
5754
5842
  const configured = settings?.identitySigningSecretConfigured ?? false;
@@ -6826,6 +6914,11 @@ async function handleTool(name, args) {
6826
6914
  const r = await messagingGet(`/IndexMove/MixedContent?index=${encodeURIComponent(args.indexName)}`);
6827
6915
  return JSON.stringify(r, null, 2);
6828
6916
  }
6917
+ case 'kb_advise_knowledge_strategy': {
6918
+ if (!Array.isArray(args.sources) || args.sources.length === 0) throw new Error('sources must be a non-empty array of { kind, ... }');
6919
+ const r = await messagingPost('/KnowledgeAdvisor/advise', { sources: args.sources });
6920
+ return JSON.stringify(r, null, 2);
6921
+ }
6829
6922
  case 'index_integrity_check': {
6830
6923
  const r = await messagingGet(`/IndexMove/Integrity?index=${encodeURIComponent(args.indexName)}`);
6831
6924
  return JSON.stringify(r, null, 2);
@@ -7267,7 +7360,7 @@ async function handleTool(name, args) {
7267
7360
  const alerts = [];
7268
7361
  if (s.disconnectEvents > 0) alerts.push(`⚠ ${s.disconnectEvents} disconnect(s)`);
7269
7362
  if (s.tabHiddenEvents > 0) alerts.push(`⚠ ${s.tabHiddenEvents} tab hidden`);
7270
- const recentDisconnects = (a.connectionEvents || []).filter(e => e.event?.toLowerCase().includes('disconnect')).slice(-3);
7363
+ const recentDisconnects = (a.connectionEvents || []).filter(e => e.event?.toLowerCase().includes('disconnect')).slice(0, 3); // connectionEvents are newest-first
7271
7364
  return [
7272
7365
  ` ${a.agentName}${a.email ? ' <' + a.email + '>' : ''}`,
7273
7366
  ` Status time: ${statusParts.join(' | ') || 'no data'}`,
@@ -8708,6 +8801,35 @@ async function handleTool(name, args) {
8708
8801
  return JSON.stringify(r, null, 2);
8709
8802
  }
8710
8803
 
8804
+ // ── Business actions + SAP ────────────────────────────────────────────────
8805
+ case 'sap_diagnose': {
8806
+ if (!args.siteId) return 'siteId is required.';
8807
+ const deep = args.deep === false ? 'false' : 'true';
8808
+ const r = await api('GET', `/diagnostics/test-sap?siteId=${encodeURIComponent(args.siteId)}&deep=${deep}`);
8809
+ return JSON.stringify(r, null, 2);
8810
+ }
8811
+
8812
+ case 'business_action_list': {
8813
+ const r = await api('GET', '/BusinessActions');
8814
+ return JSON.stringify(r, null, 2);
8815
+ }
8816
+
8817
+ case 'business_action_route': {
8818
+ if (!args.text) return 'text is required.';
8819
+ const r = await api('POST', '/BusinessActions/Route', { text: args.text, max: args.max });
8820
+ return JSON.stringify(r, null, 2);
8821
+ }
8822
+
8823
+ case 'business_action_execute': {
8824
+ if (!args.name) return 'name is required.';
8825
+ if (!args.request || typeof args.request !== 'object') return 'request (object) is required.';
8826
+ const qs = [];
8827
+ if (args.idempotencyKey) qs.push(`idempotencyKey=${encodeURIComponent(args.idempotencyKey)}`);
8828
+ if (args.conversationId) qs.push(`conversationId=${encodeURIComponent(args.conversationId)}`);
8829
+ const r = await api('POST', `/BusinessActions/${encodeURIComponent(args.name)}/Execute${qs.length ? '?' + qs.join('&') : ''}`, args.request);
8830
+ return JSON.stringify(r, null, 2);
8831
+ }
8832
+
8711
8833
  // ── CallRail Attribution ──────────────────────────────────────────────────
8712
8834
  case 'callrail_get_attributions': {
8713
8835
  const limit = Math.min(100, args.limit ?? 25);