@ateam-ai/mcp 0.4.11 → 0.4.12

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/tools.js +58 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.4.11",
3
+ "version": "0.4.12",
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/tools.js CHANGED
@@ -1121,6 +1121,24 @@ export const tools = [
1121
1121
  required: ["job_id"],
1122
1122
  },
1123
1123
  },
1124
+ {
1125
+ name: "ateam_chain_status",
1126
+ core: true,
1127
+ description:
1128
+ "SLIM chain status — the chip-quick poll. Given a chain_id (from ateam_conversation), returns the WHOLE-CHAIN aggregate status cheaply: chain_status + chain_done (true only when the ENTIRE chain — root job + every handoff + askAnySkill subcall — is terminal), plus pending_question, result, and a short progress line.\n\n" +
1129
+ "This is what you poll on a loop after ateam_conversation — NOT ateam_get_chain (that returns the full tree; too heavy for periodic polling). A single job can finish while the chain is still running, so poll chain_done, not a job's status.\n\n" +
1130
+ "Loop: call every ~2s until chain_done === true (or pending_question is set — the assistant is waiting on the user). Then read `result` / fetch the full tree once via ateam_get_chain if you need per-job detail.",
1131
+ inputSchema: {
1132
+ type: "object",
1133
+ properties: {
1134
+ chain_id: {
1135
+ type: "string",
1136
+ description: "The chain id returned by ateam_conversation (the conversation's identity). Any job id in the chain also works — Core resolves the chain aggregate.",
1137
+ },
1138
+ },
1139
+ required: ["chain_id"],
1140
+ },
1141
+ },
1124
1142
  {
1125
1143
  name: "ateam_get_widget_catalog",
1126
1144
  core: true,
@@ -1722,6 +1740,7 @@ const TENANT_TOOLS = new Set([
1722
1740
  "ateam_test_status",
1723
1741
  "ateam_test_abort",
1724
1742
  "ateam_get_chain",
1743
+ "ateam_chain_status",
1725
1744
  "ateam_get_widget_catalog",
1726
1745
  "ateam_get_connector_source",
1727
1746
  "ateam_get_metrics",
@@ -3172,7 +3191,8 @@ const handlers = {
3172
3191
  _poll: chainId
3173
3192
  ? {
3174
3193
  _note: "Conversation started (async). The reply is NOT in this response — poll the CHAIN for it.",
3175
- slim: `ateam_get_chain(job_id: "${chainId}") → chain tree + per-job status; the routed worker's terminal job carries the reply`,
3194
+ slim: `ateam_chain_status(chain_id: "${chainId}") → cheap chip-quick poll; loop ~2s until chain_done===true (whole chain terminal, not just one job). Then read result.`,
3195
+ full: `ateam_get_chain(job_id: "${chainId}") → full tree + per-job detail (heavier; use once, not in a poll loop)`,
3176
3196
  continue: kickoff?.actor_id ? `ateam_conversation(actor_id: "${kickoff.actor_id}", ...) to continue the thread` : undefined,
3177
3197
  }
3178
3198
  : undefined,
@@ -3421,6 +3441,43 @@ const handlers = {
3421
3441
  return data;
3422
3442
  },
3423
3443
 
3444
+ // SLIM chain status — the chip-quick poll. Hits Core /api/job/:id/status
3445
+ // (slimJob), which returns the WHOLE-CHAIN aggregate `chainStatus`/`chainDone`
3446
+ // (computeChainStatus over chainId) alongside the single-job status. This is
3447
+ // the right thing to poll on a loop after ateam_conversation: a single job
3448
+ // can terminate while the chain is still active — chainDone only flips when
3449
+ // the CHAIN is done. Cheap enough for periodic polling (no full tree).
3450
+ ateam_chain_status: async ({ chain_id, job_id }, sid) => {
3451
+ const id = chain_id || job_id;
3452
+ if (!id) throw new Error("chain_id required");
3453
+ const creds = getCredentials(sid);
3454
+ const apiKey = creds?.apiKey;
3455
+ if (!apiKey) throw new Error("No api_key in session — call ateam_auth(api_key) first.");
3456
+ const coreUrl = process.env.ADAS_CORE_URL || "http://adas-backend:4000";
3457
+ const res = await fetch(`${coreUrl}/api/job/${encodeURIComponent(id)}/status`, {
3458
+ method: "GET",
3459
+ headers: { "x-api-key": apiKey, "X-ADAS-SERVICE": "ateam-mcp.chain_status" },
3460
+ signal: AbortSignal.timeout(15_000),
3461
+ });
3462
+ const text = await res.text();
3463
+ let data;
3464
+ try { data = JSON.parse(text); } catch { data = { ok: false, error: text.slice(0, 400) }; }
3465
+ if (!res.ok) {
3466
+ throw new Error(`Core /api/job/${id}/status returned ${res.status}: ${data.error || JSON.stringify(data).slice(0, 200)}`);
3467
+ }
3468
+ // Surface the chain-aggregate truth as the primary fields; keep the raw
3469
+ // slim job under `job` for callers that want per-job detail.
3470
+ return {
3471
+ chain_id: data.chainId || id,
3472
+ chain_status: data.chainStatus ?? data.status ?? null,
3473
+ chain_done: data.chainDone ?? data.done ?? null,
3474
+ pending_question: data.pendingQuestion || null,
3475
+ result: data.result ?? null,
3476
+ progress: data.progress || null,
3477
+ job: data,
3478
+ };
3479
+ },
3480
+
3424
3481
  ateam_get_widget_catalog: async ({ origin, format }, sid) => {
3425
3482
  // Wraps Core's existing GET /api/ui-plugins (merged tenant plugin list)
3426
3483
  // and enriches each entry with the documentation/how-to-use layer.