@velaro/mcp-server 0.6.97 → 0.6.99
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.
- package/package.json +1 -1
- package/server.js +27 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velaro/mcp-server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.99",
|
|
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
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
* VELARO_MCP_MODE=http PORT=3000 node server.js
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
|
+
import { describeRawMeta, fetchRetry429 } from './log-search.js';
|
|
43
44
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
44
45
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
45
46
|
import {
|
|
@@ -119,11 +120,12 @@ function parseDuration(s) {
|
|
|
119
120
|
return n * 24 * 3600 * 1000;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
|
-
async function messagingApi(path, opts = {}) {
|
|
123
|
+
async function messagingApi(path, opts = {}) { // opts.timeoutMs: log searches pass 40000 (server scan budget 12 s + 6 s AI search)
|
|
123
124
|
if (!MESSAGING_API) throw new Error(
|
|
124
125
|
'VELARO_MESSAGING_API is not configured. Add "VELARO_MESSAGING_API": "https://velaro-messaging-api-staging.azurewebsites.net" to your MCP env config.'
|
|
125
126
|
);
|
|
126
|
-
|
|
127
|
+
// 429 = the server's per-instance scan gate is full: retry honouring Retry-After (GETs only; a retried POST could repeat a write).
|
|
128
|
+
const init = () => ({
|
|
127
129
|
method: opts.method ?? 'GET',
|
|
128
130
|
headers: {
|
|
129
131
|
Authorization: authHeader(),
|
|
@@ -131,8 +133,9 @@ async function messagingApi(path, opts = {}) {
|
|
|
131
133
|
...(opts.body ? { 'Content-Type': 'application/json' } : {}),
|
|
132
134
|
},
|
|
133
135
|
body: opts.body ? JSON.stringify(opts.body) : undefined,
|
|
134
|
-
signal: AbortSignal.timeout(20000),
|
|
136
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? 20000),
|
|
135
137
|
});
|
|
138
|
+
const res = (opts.method ?? 'GET') === 'GET' ? await fetchRetry429(`${MESSAGING_API}${path}`, init) : await fetch(`${MESSAGING_API}${path}`, init());
|
|
136
139
|
if (!res.ok) {
|
|
137
140
|
const text = await res.text().catch(() => '');
|
|
138
141
|
throw new Error(`Velaro Logger ${path} -> ${res.status}: ${text.slice(0, 300)}`);
|
|
@@ -7569,9 +7572,18 @@ async function handleTool(name, args) {
|
|
|
7569
7572
|
const from1h = new Date(Date.now() - 3600000).toISOString();
|
|
7570
7573
|
const velaroLoggerP = safeJson(async () => {
|
|
7571
7574
|
if (!MESSAGING_API) return { _error: 'VELARO_MESSAGING_API not set — add it to MCP env config' };
|
|
7572
|
-
|
|
7573
|
-
const
|
|
7574
|
-
|
|
7575
|
+
// Two honest reads (Opus review 2026-10-14): ERRORS use the server-side level=ERROR filter; PATTERNS are the WF-AI-ROUTE / PERF-SLOW regex (no level).
|
|
7576
|
+
const f = encodeURIComponent(from1h);
|
|
7577
|
+
// One at a time: the server runs at most 2 exact scans per instance.
|
|
7578
|
+
const errRes = await messagingApi(`/superadmin/logs/search?level=ERROR&from=${f}&take=30`, { timeoutMs: 40000 });
|
|
7579
|
+
const patRes = await messagingApi(`/superadmin/logs/search?q=${encodeURIComponent('WF-AI-ROUTE|PERF-SLOW')}®ex=true&from=${f}&take=30`, { timeoutMs: 40000 });
|
|
7580
|
+
const byId = new Map();
|
|
7581
|
+
for (const e of [...extractLogEntries(errRes), ...extractLogEntries(patRes)]) byId.set(e.id ?? `${e.timestamp}|${e.message}`, e);
|
|
7582
|
+
const found = [...byId.values()].sort((x, y) => (Date.parse(y.timestamp ?? y.LogTimestamp) || 0) - (Date.parse(x.timestamp ?? x.LogTimestamp) || 0));
|
|
7583
|
+
const verified = (r) => !!(r && !Array.isArray(r) && r.truncated === false);
|
|
7584
|
+
found._verified = verified(errRes) && verified(patRes);
|
|
7585
|
+
found._note = `errors: ${describeRawMeta(errRes)} | patterns: ${describeRawMeta(patRes)}`;
|
|
7586
|
+
return found;
|
|
7575
7587
|
});
|
|
7576
7588
|
|
|
7577
7589
|
// ── Layer 4b: Loggly ERROR + SLOW + AI-routing logs (last 1h) — SECONDARY (migrating away)
|
|
@@ -7647,9 +7659,11 @@ async function handleTool(name, args) {
|
|
|
7647
7659
|
if (velaroLogs?._error) {
|
|
7648
7660
|
out.push(section('Velaro Logger (1h) [PRIMARY]', [` ⚠ ${velaroLogs._error}`]));
|
|
7649
7661
|
} else if (!Array.isArray(velaroLogs) || !velaroLogs.length) {
|
|
7650
|
-
out.push(section('Velaro Logger (1h) [PRIMARY]',
|
|
7662
|
+
out.push(section('Velaro Logger (1h) [PRIMARY]', velaroLogs?._verified
|
|
7663
|
+
? [` ✅ No errors, slow responses, or AI routing events (${velaroLogs._note})`]
|
|
7664
|
+
: [` ⚠ No matches, but the scan is NOT verified complete: ${velaroLogs?._note ?? 'no scan metadata'}. Use velaro_logs_search before concluding all is well.`]));
|
|
7651
7665
|
} else {
|
|
7652
|
-
out.push(section(`Velaro Logger (1h) [PRIMARY] — ${velaroLogs.length} entries`, velaroLogs.map(fmtVelaroEntry)));
|
|
7666
|
+
out.push(section(`Velaro Logger (1h) [PRIMARY] — ${velaroLogs.length} entries${velaroLogs._verified ? '' : ` (scan not verified complete: ${velaroLogs._note})`}`, velaroLogs.map(fmtVelaroEntry)));
|
|
7653
7667
|
}
|
|
7654
7668
|
|
|
7655
7669
|
// ── Loggly (secondary — being phased out; check if Velaro Logger is empty/errored)
|
|
@@ -8611,9 +8625,11 @@ async function handleTool(name, args) {
|
|
|
8611
8625
|
if (args.environment) params.set('environment', args.environment);
|
|
8612
8626
|
if (args.correlationId) params.set('correlationId', args.correlationId);
|
|
8613
8627
|
if (args.regex) params.set('regex', 'true');
|
|
8614
|
-
const
|
|
8615
|
-
|
|
8616
|
-
const
|
|
8628
|
+
const resp = await messagingApi(`/superadmin/logs/search?${params}`, { timeoutMs: 40000 });
|
|
8629
|
+
const entries = extractLogEntries(resp);
|
|
8630
|
+
const meta = describeRawMeta(resp); // searchPath/scannedRows/truncated: a 0 or short list is never ambiguous
|
|
8631
|
+
if (!entries.length) return `No results. ${meta}`;
|
|
8632
|
+
const lines = [`${entries.length} result(s) from ${from.toISOString().slice(0, 16)} UTC. ${meta}\n`];
|
|
8617
8633
|
for (const e of entries) {
|
|
8618
8634
|
const ts = new Date(e.timestamp ?? e.LogTimestamp).toISOString().replace('T', ' ').slice(0, 19);
|
|
8619
8635
|
const lvl = (e.Level ?? e.level ?? '?').padEnd(5);
|