@ateam-ai/mcp 0.4.44 → 0.4.46

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/package.json +1 -1
  2. package/src/api.js +21 -1
  3. package/src/tools.js +19 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.4.44",
3
+ "version": "0.4.46",
4
4
  "mcpName": "io.github.ariekogan/ateam-mcp",
5
5
  "description": "A-Team MCP Server — build, validate, and deploy multi-agent solutions from any AI environment",
6
6
  "type": "module",
package/src/api.js CHANGED
@@ -461,7 +461,21 @@ function formatError(method, path, status, body, baseUrl) {
461
461
  }
462
462
 
463
463
  const hint = hints[status] || "";
464
- const detail = typeof body === "string" && body.length > 0 && body.length < 2000 ? body : "";
464
+ // A JSON error body used to be dropped entirely only a string body became
465
+ // `detail`. So an endpoint that answers 4xx WITH the diagnosis (ui.surfaceProbe
466
+ // returns 422 + the failures that explain why the surface is broken) reached
467
+ // the caller as a bare "returned 422", throwing away the very thing it was
468
+ // asked to produce. Serialize objects too, capped the same way.
469
+ let detail = "";
470
+ const asText = typeof body === "string"
471
+ ? body
472
+ : (body && typeof body === "object" ? (() => { try { return JSON.stringify(body); } catch { return ""; } })() : "");
473
+ if (asText.length > 0) {
474
+ // Previously a body of 2000+ chars was dropped ENTIRELY, so the richer the
475
+ // error the less the caller was told — a 422 carrying the full diagnosis
476
+ // arrived as a bare status code. Truncate instead of discarding.
477
+ detail = asText.length < 2000 ? asText : asText.slice(0, 2000) + "… (truncated)";
478
+ }
465
479
 
466
480
  // Always show the FULL URL actually hit — ateam-mcp is a PUBLIC MCP with a
467
481
  // configurable base (prod default, dev/self-host overrides), so a bare
@@ -525,6 +539,12 @@ async function request(method, path, body, sessionId, opts = {}) {
525
539
  // on this to NOT scaffold-clobber an existing skill on a read error.
526
540
  const e = new Error(formatError(method, path, res.status, text, baseUrl));
527
541
  e.status = res.status;
542
+ // Keep the RAW body on the error. formatError truncates for humans, and
543
+ // an endpoint that answers 4xx WITH the diagnosis (ui.surfaceProbe's 422
544
+ // carries the failures explaining why a surface is broken) is exactly the
545
+ // case where the body matters more than the status. A caller that knows
546
+ // how to read its own error shape should not have to scrape a message.
547
+ e.body = text;
528
548
  throw e;
529
549
  }
530
550
 
package/src/tools.js CHANGED
@@ -4036,10 +4036,25 @@ const handlers = {
4036
4036
  if (actor_id) body.actor_id = actor_id;
4037
4037
  // Forwards to the skill-validator, which runs Core's ui.surfaceProbe via /mcp.
4038
4038
  // 60s: navigate + settle + warm-retry inside Core, plus the hop.
4039
- return await post(
4040
- `/deploy/solutions/${solution_id}/plugins/${encodeURIComponent(plugin_id)}/verify-surface`,
4041
- body, sid, { timeoutMs: 60000 }
4042
- );
4039
+ try {
4040
+ return await post(
4041
+ `/deploy/solutions/${solution_id}/plugins/${encodeURIComponent(plugin_id)}/verify-surface`,
4042
+ body, sid, { timeoutMs: 60000 }
4043
+ );
4044
+ } catch (err) {
4045
+ // A FAILING surface is this tool's whole job, not a transport error. The
4046
+ // route maps a negative verdict to 422 (503 for inconclusive), which the
4047
+ // generic error path turned into "returned 422" — hiding the failures that
4048
+ // say WHY the screen is broken, and leaving the caller as blind as before
4049
+ // it ran the probe. Hand the verdict back as a result instead of throwing.
4050
+ if (typeof err?.body === "string" && err.body) {
4051
+ try {
4052
+ const parsed = JSON.parse(err.body);
4053
+ if (parsed && (parsed.verdict || Array.isArray(parsed.failures))) return parsed;
4054
+ } catch { /* not the probe's body — fall through */ }
4055
+ }
4056
+ throw err;
4057
+ }
4043
4058
  },
4044
4059
 
4045
4060
  ateam_test_skill: async ({ solution_id, skill_id, message, wait, wait_for, chain_timeout_ms, actor_id }, sid) => {