@ateam-ai/mcp 0.4.75 → 0.4.77
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/src/tools.js +92 -1
package/package.json
CHANGED
package/src/tools.js
CHANGED
|
@@ -2241,6 +2241,24 @@ export const tools = [
|
|
|
2241
2241
|
required: ["solution_id"],
|
|
2242
2242
|
},
|
|
2243
2243
|
},
|
|
2244
|
+
{
|
|
2245
|
+
name: "ateam_github_reconcile",
|
|
2246
|
+
core: true,
|
|
2247
|
+
description:
|
|
2248
|
+
"JOIN a diverged dev and main. Use when ateam_github_promote returns PROMOTE_NEEDS_HUMAN or PROMOTE_PRECONDITION_FAILED — i.e. the automatic main→dev back-merge could not resolve itself.\n\n" +
|
|
2249
|
+
"TRY sync_from_main FIRST; this tool calls it internally (a plain merge keeps both sides with no judgement call) and only escalates when git genuinely conflicts.\n\n" +
|
|
2250
|
+
"On conflict it writes a TWO-PARENT merge commit so the histories actually join. That matters: copying one branch's tree onto the other makes the contents match while leaving NO merge base, so the very next promote conflicts again — equal content is not a reconciled history.\n\n" +
|
|
2251
|
+
"Conflicting files are resolved per file, NEWEST WINS, and every decision is reported. Recency is a heuristic, not intent: read the decisions. On a real tenant main held the newer solution.json while dev held the newer widget, so a blanket choice would have reverted one of them.\n\n" +
|
|
2252
|
+
"WHO NEEDS THIS: any tenant whose deploys predate the dev-routing fix carries main-only commits the platform itself wrote, and hits this on its first promote afterwards. Pass dry_run:true to see the decisions before writing anything.",
|
|
2253
|
+
inputSchema: {
|
|
2254
|
+
type: "object",
|
|
2255
|
+
properties: {
|
|
2256
|
+
solution_id: { type: "string", description: "The solution ID" },
|
|
2257
|
+
dry_run: { type: "boolean", description: "Report the per-file decisions without writing the merge commit." },
|
|
2258
|
+
},
|
|
2259
|
+
required: ["solution_id"],
|
|
2260
|
+
},
|
|
2261
|
+
},
|
|
2244
2262
|
{
|
|
2245
2263
|
name: "ateam_github_sync_from_main",
|
|
2246
2264
|
core: true,
|
|
@@ -5329,10 +5347,78 @@ const handlers = {
|
|
|
5329
5347
|
gaps.push(`solution health unavailable: ${e.message}`);
|
|
5330
5348
|
}
|
|
5331
5349
|
|
|
5350
|
+
// 4. SMOKE CALL — actually invoke a tool the SOLUTION depends on.
|
|
5351
|
+
//
|
|
5352
|
+
// Everything above is tools/list-level: `connected`, `tools > 0`, "renders",
|
|
5353
|
+
// "deployed". All of it stayed green on a clinic connector that answered
|
|
5354
|
+
// tools/list correctly and returned 401 on EVERY storage call, because its
|
|
5355
|
+
// generated client put a PAT in the shared-secret header. The build shipped,
|
|
5356
|
+
// reported healthy, and failed the first time a user touched it. The only
|
|
5357
|
+
// check that could have caught it is calling something.
|
|
5358
|
+
//
|
|
5359
|
+
// Tool names come from the SKILLS, not the connector: the connector
|
|
5360
|
+
// endpoints expose a count and a description but no name (verified live —
|
|
5361
|
+
// /connectors/<id>/tools returns 7 objects that are all {description:""}),
|
|
5362
|
+
// and the tools a skill declares are the ones that actually have to work.
|
|
5363
|
+
// Testing those is a better question than testing an arbitrary one.
|
|
5364
|
+
out.smoke = [];
|
|
5365
|
+
try {
|
|
5366
|
+
const wanted = new Map(); // toolName -> connectorId (first skill that declares it)
|
|
5367
|
+
for (const sk of Array.isArray(out.skills) ? out.skills : []) {
|
|
5368
|
+
if (!sk?.id) continue;
|
|
5369
|
+
const def = await get(`/deploy/solutions/${solution_id}/skills/${sk.id}`, sid).catch(() => null);
|
|
5370
|
+
for (const t of (def?.skill?.tools || def?.tools || [])) {
|
|
5371
|
+
const name = typeof t === "string" ? t : t?.name;
|
|
5372
|
+
if (!name || wanted.has(name)) continue;
|
|
5373
|
+
const conn = (typeof t === "object" && (t?.source?.connector || t?.source?.id)) || null;
|
|
5374
|
+
wanted.set(name, conn);
|
|
5375
|
+
}
|
|
5376
|
+
}
|
|
5377
|
+
|
|
5378
|
+
// READ-SHAPED ONLY. A smoke test must never book an appointment or delete a
|
|
5379
|
+
// row to prove a connector is alive, so a write-shaped name is skipped and
|
|
5380
|
+
// SAID to be skipped rather than quietly passed over.
|
|
5381
|
+
const readish = [...wanted.keys()].filter((n) => /(^|[._])(list|get|today|available|health|status|ping|info|search)([._]|$)/i.test(n));
|
|
5382
|
+
const perConnector = new Map();
|
|
5383
|
+
for (const name of readish) {
|
|
5384
|
+
const conn = wanted.get(name) || (Array.isArray(out.connectors) && out.connectors[0]?.id) || null;
|
|
5385
|
+
if (!conn || perConnector.has(conn)) continue;
|
|
5386
|
+
perConnector.set(conn, name);
|
|
5387
|
+
}
|
|
5388
|
+
|
|
5389
|
+
for (const c of Array.isArray(out.connectors) ? out.connectors : []) {
|
|
5390
|
+
// DELIBERATELY NOT GATED ON c.connected. Connectors are LAZY — one idles
|
|
5391
|
+
// back to sleep between step 1 and here, and the /call endpoint wakes it
|
|
5392
|
+
// on demand. Skipping a sleeping connector would make this check silently
|
|
5393
|
+
// untestable exactly when it is most needed, and "asleep" is not an
|
|
5394
|
+
// answer to "do its calls work?". The call itself is the verdict.
|
|
5395
|
+
const pick = perConnector.get(c.id);
|
|
5396
|
+
if (!pick) {
|
|
5397
|
+
out.smoke.push({ connector: c.id, called: null, note: "no read-shaped tool declared by any skill — NOT smoke-tested" });
|
|
5398
|
+
gaps.push(`connector '${c.id}' was not smoke-tested (no read-shaped tool declared by a skill); tools/list working does NOT prove its calls succeed`);
|
|
5399
|
+
continue;
|
|
5400
|
+
}
|
|
5401
|
+
try {
|
|
5402
|
+
const r = await post(`/deploy/solutions/${solution_id}/connectors/${c.id}/call`, { tool: pick, args: {} }, sid);
|
|
5403
|
+
const failed = r?.ok === false;
|
|
5404
|
+
out.smoke.push({ connector: c.id, called: pick, ok: !failed, ...(failed && { error: String(r?.error || "").slice(0, 200) }) });
|
|
5405
|
+
if (failed) {
|
|
5406
|
+
gaps.push(`connector '${c.id}' lists ${c.tools} tool(s) but CALLING ${pick} failed: ${String(r?.error || "").slice(0, 160)} — tools/list works and real calls do not`);
|
|
5407
|
+
}
|
|
5408
|
+
} catch (e) {
|
|
5409
|
+
out.smoke.push({ connector: c.id, called: pick, ok: false, error: e.message.slice(0, 200) });
|
|
5410
|
+
gaps.push(`connector '${c.id}' smoke call ${pick} errored: ${e.message.slice(0, 160)}`);
|
|
5411
|
+
}
|
|
5412
|
+
}
|
|
5413
|
+
} catch (e) {
|
|
5414
|
+
out.smoke = { error: e.message };
|
|
5415
|
+
gaps.push(`smoke check could not run: ${e.message}`);
|
|
5416
|
+
}
|
|
5417
|
+
|
|
5332
5418
|
out.gaps = gaps;
|
|
5333
5419
|
out.ok = gaps.length === 0;
|
|
5334
5420
|
out._status = out.ok
|
|
5335
|
-
? "✅ Verified live — connectors connected, widgets render, skills deployed."
|
|
5421
|
+
? "✅ Verified live — connectors connected AND answering real calls, widgets render, skills deployed."
|
|
5336
5422
|
: `⚠️ ${gaps.length} gap(s): ${gaps.slice(0, 5).join("; ")}${gaps.length > 5 ? " …" : ""}`;
|
|
5337
5423
|
return out;
|
|
5338
5424
|
},
|
|
@@ -5412,6 +5498,11 @@ const handlers = {
|
|
|
5412
5498
|
ateam_github_promote: async ({ solution_id, label, dry_run, skip_tag }, sid) =>
|
|
5413
5499
|
post(`/deploy/solutions/${solution_id}/promote`, { label, dry_run, skip_tag }, sid),
|
|
5414
5500
|
|
|
5501
|
+
ateam_github_reconcile: async ({ solution_id, dry_run }, sid) => {
|
|
5502
|
+
if (!solution_id) throw new Error("solution_id required");
|
|
5503
|
+
return await post(`/deploy/solutions/${solution_id}/reconcile`, { dry_run: dry_run === true }, sid);
|
|
5504
|
+
},
|
|
5505
|
+
|
|
5415
5506
|
ateam_github_sync_from_main: async ({ solution_id, dry_run }, sid) =>
|
|
5416
5507
|
post(`/deploy/solutions/${solution_id}/sync-from-main`, { dry_run }, sid),
|
|
5417
5508
|
|