@agentvalet/mcp-server 0.3.2 → 0.3.4
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/dist/index.js +71 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -325,6 +325,40 @@ async function fetchWithAuth(url, init) {
|
|
|
325
325
|
function errorContent(message) {
|
|
326
326
|
return { content: [{ type: "text", text: message }], isError: true };
|
|
327
327
|
}
|
|
328
|
+
// Return helper that gives an MCP-aware host the structured content directly
|
|
329
|
+
// (no parse step), while still emitting the text-content envelope every MCP
|
|
330
|
+
// client understands. Avoids the "list of length 1 with empty fields → let me
|
|
331
|
+
// parse the wrapper" round-trip Claude does on tool results that are raw
|
|
332
|
+
// JSON strings — every read-heavy use_platform call pays that cost otherwise.
|
|
333
|
+
//
|
|
334
|
+
// If `body` isn't valid JSON, we just return the text envelope unchanged —
|
|
335
|
+
// callers that emit prose (summaries, error strings) get the old behaviour.
|
|
336
|
+
function jsonContent(body) {
|
|
337
|
+
const parsed = tryParseJson(body);
|
|
338
|
+
if (parsed === undefined) {
|
|
339
|
+
return { content: [{ type: "text", text: body }] };
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
content: [{ type: "text", text: body }],
|
|
343
|
+
structuredContent: parsed,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function tryParseJson(text) {
|
|
347
|
+
const trimmed = text.trim();
|
|
348
|
+
// Only attempt parse if it looks structured. Avoids parsing a stray "true"
|
|
349
|
+
// / number / etc. into structuredContent and confusing the host.
|
|
350
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("["))
|
|
351
|
+
return undefined;
|
|
352
|
+
try {
|
|
353
|
+
const v = JSON.parse(trimmed);
|
|
354
|
+
if (v && typeof v === "object")
|
|
355
|
+
return v;
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
328
362
|
// ---------------------------------------------------------------------------
|
|
329
363
|
// Tool handlers
|
|
330
364
|
// ---------------------------------------------------------------------------
|
|
@@ -338,12 +372,34 @@ async function handleListPlatforms() {
|
|
|
338
372
|
response = await fetchWithAuth(`${PROXY_URL}/v1/agent/permissions`, { method: "GET", headers: {} });
|
|
339
373
|
}
|
|
340
374
|
catch (err) {
|
|
341
|
-
return errorContent(
|
|
375
|
+
return errorContent(diagnoseNetworkError(err, PROXY_URL));
|
|
342
376
|
}
|
|
343
377
|
const body = await response.text();
|
|
344
378
|
if (!response.ok)
|
|
345
379
|
return errorContent(`Proxy error ${response.status}: ${body}`);
|
|
346
|
-
return
|
|
380
|
+
return jsonContent(body);
|
|
381
|
+
}
|
|
382
|
+
// Translates a fetch() failure into something an end-user can actually act on.
|
|
383
|
+
// The default "Network error: fetch failed" message tells a non-developer
|
|
384
|
+
// nothing. Look at the underlying cause keyword and map to a concrete fix.
|
|
385
|
+
function diagnoseNetworkError(err, proxyUrl) {
|
|
386
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
387
|
+
const lower = raw.toLowerCase();
|
|
388
|
+
// Node's undici surfaces DNS failures as "getaddrinfo ENOTFOUND <host>".
|
|
389
|
+
if (lower.includes("enotfound") || lower.includes("getaddrinfo")) {
|
|
390
|
+
return `Network error: cannot resolve ${proxyUrl}. Check your DNS / corporate proxy / VPN, or confirm the PROXY_URL setting is correct. Raw: ${raw}`;
|
|
391
|
+
}
|
|
392
|
+
// Connection refused / unreachable / TLS handshake failure.
|
|
393
|
+
if (lower.includes("econnrefused") || lower.includes("econnreset")) {
|
|
394
|
+
return `Network error: connection to ${proxyUrl} was refused or reset. The proxy may be down — check https://status.agentvalet.ai — or a firewall is blocking the request. Raw: ${raw}`;
|
|
395
|
+
}
|
|
396
|
+
if (lower.includes("etimedout") || lower.includes("timeout") || lower.includes("aborterror")) {
|
|
397
|
+
return `Network error: request to ${proxyUrl} timed out. Likely causes: VPN routing, corporate proxy buffering, or slow network. Try again or confirm api.agentvalet.ai is reachable from this machine. Raw: ${raw}`;
|
|
398
|
+
}
|
|
399
|
+
if (lower.includes("self signed") || lower.includes("cert") || lower.includes("ssl") || lower.includes("tls")) {
|
|
400
|
+
return `Network error: TLS / certificate problem talking to ${proxyUrl}. A corporate MITM proxy may be intercepting traffic. Raw: ${raw}`;
|
|
401
|
+
}
|
|
402
|
+
return `Network error reaching ${proxyUrl}: ${raw}. Check VPN, corporate proxy, and firewall rules for api.agentvalet.ai. If the proxy itself is down, see https://status.agentvalet.ai.`;
|
|
347
403
|
}
|
|
348
404
|
// Long-poll budget — under Claude Desktop's hardcoded 60s tool timeout
|
|
349
405
|
// (with 10s of safety). After this we return a graceful "queued" message and
|
|
@@ -387,7 +443,7 @@ async function handleUsePlatform(params, progressToken) {
|
|
|
387
443
|
}
|
|
388
444
|
if (!response.ok)
|
|
389
445
|
return errorContent(`Proxy error ${response.status}: ${body}`);
|
|
390
|
-
return
|
|
446
|
+
return jsonContent(body);
|
|
391
447
|
}
|
|
392
448
|
async function waitForApproval(approvalId, originalCall, progressToken) {
|
|
393
449
|
const startedAt = Date.now();
|
|
@@ -443,18 +499,13 @@ async function waitForApproval(approvalId, originalCall, progressToken) {
|
|
|
443
499
|
// Timed out — fall through to async-recap path. The action is still
|
|
444
500
|
// queued and will run when the owner approves; the user is notified via
|
|
445
501
|
// push/email at that point. Layer 4's list_my_pending_actions surfaces it.
|
|
446
|
-
return {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
`The action is queued — your owner will be notified, and you'll see it ` +
|
|
454
|
-
`complete next time we chat (or you can ask me to check pending actions).`,
|
|
455
|
-
}),
|
|
456
|
-
}],
|
|
457
|
-
};
|
|
502
|
+
return jsonContent(JSON.stringify({
|
|
503
|
+
status: "pending_approval",
|
|
504
|
+
approval_id: approvalId,
|
|
505
|
+
message: `Owner hasn't approved within ${APPROVAL_POLL_BUDGET_MS / 1000}s. ` +
|
|
506
|
+
`The action is queued — your owner will be notified, and you'll see it ` +
|
|
507
|
+
`complete next time we chat (or you can ask me to check pending actions).`,
|
|
508
|
+
}));
|
|
458
509
|
}
|
|
459
510
|
function safeJsonParse(text) {
|
|
460
511
|
try {
|
|
@@ -495,7 +546,7 @@ async function handleAgentRegister(args) {
|
|
|
495
546
|
const body = await response.text();
|
|
496
547
|
if (!response.ok)
|
|
497
548
|
return errorContent(`Proxy error ${response.status}: ${body}`);
|
|
498
|
-
return
|
|
549
|
+
return jsonContent(body);
|
|
499
550
|
}
|
|
500
551
|
async function handleAgentStatus(token) {
|
|
501
552
|
let response;
|
|
@@ -511,7 +562,7 @@ async function handleAgentStatus(token) {
|
|
|
511
562
|
const body = await response.text();
|
|
512
563
|
if (!response.ok)
|
|
513
564
|
return errorContent(`Proxy error ${response.status}: ${body}`);
|
|
514
|
-
return
|
|
565
|
+
return jsonContent(body);
|
|
515
566
|
}
|
|
516
567
|
async function handleAuthzenEvaluate(platformId, scope) {
|
|
517
568
|
const authzenBody = {
|
|
@@ -532,7 +583,7 @@ async function handleAuthzenEvaluate(platformId, scope) {
|
|
|
532
583
|
const body = await response.text();
|
|
533
584
|
if (!response.ok)
|
|
534
585
|
return errorContent(`Proxy error ${response.status}: ${body}`);
|
|
535
|
-
return
|
|
586
|
+
return jsonContent(body);
|
|
536
587
|
}
|
|
537
588
|
async function handleListMyPendingActions() {
|
|
538
589
|
if (AGENT_PRIVATE_KEY_RAW === null) {
|
|
@@ -549,7 +600,7 @@ async function handleListMyPendingActions() {
|
|
|
549
600
|
const text = await response.text();
|
|
550
601
|
if (!response.ok)
|
|
551
602
|
return errorContent(`Proxy error ${response.status}: ${text}`);
|
|
552
|
-
return
|
|
603
|
+
return jsonContent(text);
|
|
553
604
|
}
|
|
554
605
|
async function handleReportSelfDiagnostic(args) {
|
|
555
606
|
if (AGENT_PRIVATE_KEY_RAW === null) {
|
|
@@ -578,7 +629,7 @@ async function handleReportSelfDiagnostic(args) {
|
|
|
578
629
|
const text = await response.text();
|
|
579
630
|
if (!response.ok)
|
|
580
631
|
return errorContent(`Proxy error ${response.status}: ${text}`);
|
|
581
|
-
return
|
|
632
|
+
return jsonContent(text);
|
|
582
633
|
}
|
|
583
634
|
// ---------------------------------------------------------------------------
|
|
584
635
|
// Connect transport
|