@ateam-ai/mcp 0.4.29 → 0.4.31

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 +40 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.4.29",
3
+ "version": "0.4.31",
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
@@ -102,14 +102,14 @@ function _summarizeDef(def) {
102
102
  ...(def.connectors && { connectors: pick(def.connectors, "id") }),
103
103
  ...(def.platform_connectors && { platform_connectors: pick(def.platform_connectors, "id") }),
104
104
  ...(def.ui_plugins && { ui_plugins: pick(def.ui_plugins, "id") }),
105
- ...(def.tools && { tools: pick(def.tools, "name") }),
106
- // OPEN-20: connector-imported tools don't all appear as literal entries in
107
- // `tools` they come from `toolbox_imports` and/or wildcard entries like
108
- // "connector-id:*" that EXPAND to every tool of that connector at runtime.
109
- // Surface both so an agent doesn't read a real runtime tool as "missing".
110
- ...(def.toolbox_imports && { toolbox_imports: pick(def.toolbox_imports, "connector_id") || def.toolbox_imports }),
111
- ...((Array.isArray(def.tools) && def.tools.some((t) => typeof (t?.name) === "string" && t.name.endsWith(":*"))) && {
112
- _tools_note: "Entries ending ':*' (or toolbox_imports) grant ALL of that connector's tools at RUNTIME — the specific tool names (e.g. 'connector.foo.get') are callable even though they aren't listed literally here. Verify with a live test_skill / connectors_health, not this summary.",
105
+ // OPEN-20: `tools` here are the DECLARED tools only. A skill's REAL callable
106
+ // set also includes every tool of each connector in `connectors[]` — Core
107
+ // auto-imports those at deploy, so they're callable at runtime even though
108
+ // they're NOT listed here. So this summary UNDER-reports the toolset; don't
109
+ // read a connector tool's absence as "missing".
110
+ ...(def.tools && { tools_declared: pick(def.tools, "name") }),
111
+ ...((Array.isArray(def.connectors) && def.connectors.length > 0) && {
112
+ _tools_note: `Callable tools = tools_declared + ALL tools from linked connectors [${pick(def.connectors, "id").join(", ")}] (Core auto-imports them at deployNOT listed above). For the real runtime set use ateam_get_solution(view:"connectors_health") or a live ateam_test_skill; a connector tool (e.g. 'connector.foo.get') is callable via the LINK even if it isn't in tools_declared.`,
113
113
  }),
114
114
  _fields: Object.keys(def),
115
115
  _note: "compact summary — pass include_definition:true to ateam_patch for the full definition.",
@@ -3159,6 +3159,8 @@ const handlers = {
3159
3159
  ateam_patch: async ({ solution_id, target, skill_id, updates, test_message, dry_run, source, include_definition }, sid) => {
3160
3160
  const phases = [];
3161
3161
  let isNewSkill = false;
3162
+ let _connectorToolPush = null;
3163
+ let writeBranch = "dev"; // github/patch default; overwritten by the actual response branch
3162
3164
  const _diff = { arrays_merged: [], arrays_replaced: [], scalars_changed: [], sections_replaced: [] };
3163
3165
 
3164
3166
  // Two backing stores, chosen EXPLICITLY by `source` (never inferred):
@@ -3258,6 +3260,18 @@ const handlers = {
3258
3260
  const field = key.replace(/_push$/, "");
3259
3261
  const { parent, leaf } = _resolveDottedField(patched, field);
3260
3262
  parent[leaf] = [...(Array.isArray(parent[leaf]) ? parent[leaf] : []), ...value];
3263
+ // Record the merge so a successful push is NOT reported as an empty
3264
+ // diff / silent no-op (OPEN-21 reporting gap).
3265
+ _diff.arrays_merged.push({ field, added: value.length });
3266
+ // OPEN-21: a connector's tools are granted by LINKING the connector
3267
+ // (connectors_push), NOT by pushing a definition into tools[]. Flag an
3268
+ // obviously connector-served push so we can redirect the agent.
3269
+ if (field === "tools") {
3270
+ const connectorish = value
3271
+ .filter((t) => t?.source?.type === "mcp_bridge" || (typeof t?.name === "string" && t.name.endsWith(":*")))
3272
+ .map((t) => t?.name).filter(Boolean);
3273
+ if (connectorish.length) _connectorToolPush = connectorish;
3274
+ }
3261
3275
  } else if (key.endsWith("_delete")) {
3262
3276
  if (!Array.isArray(value)) {
3263
3277
  return { ok: false, phase: "patch", error: `${key} requires an array of names/ids (got ${typeof value}). Pass {"${key}": ["name1", "name2"]}.` };
@@ -3403,12 +3417,17 @@ const handlers = {
3403
3417
  phases.push({ phase: "local_write", status: "done" });
3404
3418
  }
3405
3419
  } else {
3406
- await post(`/deploy/solutions/${solution_id}/github/patch`, {
3420
+ // github/patch writes to `dev` by default (agents don't edit prod
3421
+ // directly). Capture the ACTUAL branch it committed to — do NOT assume
3422
+ // 'main'; mislabeling it strands the change off `main` until an explicit
3423
+ // ateam_github_promote (was: the result hardcoded branch:"main").
3424
+ const ghResp = await post(`/deploy/solutions/${solution_id}/github/patch`, {
3407
3425
  path: filePath,
3408
3426
  content: JSON.stringify(patched, null, 2),
3409
3427
  message,
3410
3428
  }, sid, { timeoutMs: 30_000 });
3411
- phases.push({ phase: "github_write", status: "done" });
3429
+ writeBranch = ghResp?.branch || writeBranch;
3430
+ phases.push({ phase: "github_write", status: "done", branch: writeBranch });
3412
3431
  }
3413
3432
  } catch (err) {
3414
3433
  const store = isLocal ? "Builder store (local)" : "GitHub";
@@ -3507,7 +3526,12 @@ const handlers = {
3507
3526
  ok: true,
3508
3527
  solution_id,
3509
3528
  source: isLocal ? "local" : "github",
3510
- ...(isLocal ? {} : { branch: 'main' }),
3529
+ ...(isLocal ? {} : {
3530
+ branch: writeBranch,
3531
+ // Be explicit: a github write lands on `dev`, not prod. The change is
3532
+ // NOT on `main` until an explicit ateam_github_promote(dev→main).
3533
+ ...(writeBranch !== "main" && { _branch_note: `Committed to "${writeBranch}" (not main). Run ateam_github_promote(solution_id) to ship dev→main; otherwise a future build_and_run(main) won't include this.` }),
3534
+ }),
3511
3535
  phases,
3512
3536
  // The full patched definition can be 10s of KB and pushes the rest of the
3513
3537
  // result (redeploy status, widget_health) past the ~50KB output ceiling,
@@ -3516,6 +3540,11 @@ const handlers = {
3516
3540
  ...(include_definition
3517
3541
  ? { patched }
3518
3542
  : { patched_summary: _summarizeDef(patched) }),
3543
+ _diff,
3544
+ ...(_connectorToolPush && {
3545
+ _connector_tool_hint:
3546
+ `Heads up: ${_connectorToolPush.join(", ")} look like CONNECTOR-served tools. A skill gains a connector's tools by LINKING the connector — updates:{ "connectors_push": ["<connector-id>"] } — NOT by pushing a definition into tools[]; Core auto-imports the connector's live tools at deploy. tools_push is only for the skill's OWN tool definitions.`,
3547
+ }),
3519
3548
  ...(isNewSkill && { created_skill: skill_id }),
3520
3549
  ...(redeployResult && { redeploy: redeployResult }),
3521
3550
  ...(widget_health && { widget_health }),