@ateam-ai/mcp 0.3.21 → 0.3.22

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 +82 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.3.21",
3
+ "version": "0.3.22",
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
@@ -303,7 +303,9 @@ export const tools = [
303
303
  "- Update problem: updates: { \"problem.statement\": \"...\", \"problem.goals\": [\"goal1\"] }\n" +
304
304
  "- Add a tool: updates: { \"tools_push\": [{ name: \"conn.tool\", description: \"...\", inputs: [...], output: {...} }] }\n" +
305
305
  "- Change intent: updates: { \"intents.supported_update\": [{ id: \"i1\", description: \"new desc\" }] }\n" +
306
- "- Force redeploy: updates: { \"_force_redeploy\": true }\n\n" +
306
+ "- Force redeploy: updates: { \"_force_redeploy\": true }\n" +
307
+ "- CREATE a new skill: target='skill', skill_id='my-new-skill', updates: { \"problem.statement\": \"...\", \"role.persona\": \"...\" }\n" +
308
+ " If the skill doesn't exist yet, a default scaffold is created and the updates are applied on top. The skill is automatically added to the solution topology.\n\n" +
307
309
  "Use target='skill' + skill_id for skill fields. Use target='solution' for solution-level fields (linked_skills, platform_connectors, ui_plugins).",
308
310
  inputSchema: {
309
311
  type: "object",
@@ -1659,11 +1661,12 @@ const handlers = {
1659
1661
 
1660
1662
  ateam_patch: async ({ solution_id, target, skill_id, updates, test_message }, sid) => {
1661
1663
  const phases = [];
1664
+ let isNewSkill = false;
1662
1665
 
1663
1666
  // GitHub-first patch: read from GitHub → apply patch → write back → redeploy
1664
1667
  // This ensures GitHub stays the single source of truth.
1665
1668
 
1666
- // Phase 1: Read current state from GitHub
1669
+ // Phase 1: Read current state from GitHub (or create scaffold if new skill)
1667
1670
  let current;
1668
1671
  const filePath = target === "skill" && skill_id
1669
1672
  ? `skills/${skill_id}/skill.json`
@@ -1672,7 +1675,38 @@ const handlers = {
1672
1675
  const readResult = await get(`/deploy/solutions/${solution_id}/github/read?path=${encodeURIComponent(filePath)}`, sid);
1673
1676
  current = JSON.parse(readResult.content);
1674
1677
  } catch (err) {
1675
- return { ok: false, phase: "read", error: `Failed to read ${filePath} from GitHub: ${err.message}` };
1678
+ // If it's a skill that doesn't exist yet, create a default scaffold.
1679
+ // This lets agents use ateam_patch to both CREATE and UPDATE skills —
1680
+ // no separate "create" step needed.
1681
+ if (target === "skill" && skill_id) {
1682
+ console.log(`[ateam_patch] Skill "${skill_id}" not found on GitHub — creating new skill scaffold`);
1683
+ isNewSkill = true;
1684
+ current = {
1685
+ id: skill_id,
1686
+ name: skill_id.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase()),
1687
+ description: "",
1688
+ version: "0.1.0",
1689
+ phase: "PROBLEM_DISCOVERY",
1690
+ connectors: [],
1691
+ problem: { statement: "", context: "", goals: [] },
1692
+ scenarios: [],
1693
+ role: { name: "", persona: "", goals: [], limitations: [], communication_style: { tone: "professional", verbosity: "concise" } },
1694
+ intents: { supported: [], thresholds: { accept: 0.8, clarify: 0.5, reject: 0.5 }, out_of_domain: { action: "redirect", message: "" } },
1695
+ tools: [],
1696
+ policy: { guardrails: { never: [], always: [] }, approvals: [], workflows: [], escalation: { enabled: false, conditions: [], target: "" } },
1697
+ engine: { rv2: { max_iterations: 10, iteration_timeout_ms: 120000, allow_parallel_tools: false, on_max_iterations: "ask_user" }, hlr: { enabled: true, critic: { enabled: true, check_interval: 3, strictness: "medium" }, reflection: { enabled: true, depth: "shallow" }, replanning: { enabled: true, max_replans: 3 } }, autonomy: { level: "supervised" }, finalization_gate: { enabled: true, max_retries: 2 } },
1698
+ access_policy: { rules: [{ tools: ["*"], effect: "allow" }] },
1699
+ grant_mappings: [],
1700
+ channels: [],
1701
+ conversation: [],
1702
+ triggers: [],
1703
+ meta_tools: [],
1704
+ glossary: {},
1705
+ };
1706
+ phases.push({ phase: "read", status: "created_scaffold", skill_id });
1707
+ } else {
1708
+ return { ok: false, phase: "read", error: `Failed to read ${filePath} from GitHub: ${err.message}` };
1709
+ }
1676
1710
  }
1677
1711
 
1678
1712
  // Phase 2: Apply patch in memory
@@ -1730,23 +1764,52 @@ const handlers = {
1730
1764
  return { ok: false, phase: "github_write", error: `Patch applied but failed to write to GitHub: ${err.message}`, phases };
1731
1765
  }
1732
1766
 
1733
- // Phase 4: Redeploy from GitHub
1767
+ // Phase 3b: If new skill, add it to solution.json topology (skills[], linked_skills)
1768
+ if (isNewSkill && skill_id) {
1769
+ try {
1770
+ const solRead = await get(`/deploy/solutions/${solution_id}/github/read?path=solution.json`, sid);
1771
+ const sol = JSON.parse(solRead.content);
1772
+ const skillEntry = { id: skill_id, name: patched.name || skill_id, role: "worker", description: patched.description || "", connectors: patched.connectors || [] };
1773
+ // Add to skills[] if not already present
1774
+ if (!sol.skills) sol.skills = [];
1775
+ if (!sol.skills.find(s => s.id === skill_id)) {
1776
+ sol.skills.push(skillEntry);
1777
+ }
1778
+ // Add to linked_skills if not already present
1779
+ if (!sol.linked_skills) sol.linked_skills = [];
1780
+ if (!sol.linked_skills.includes(skill_id)) {
1781
+ sol.linked_skills.push(skill_id);
1782
+ }
1783
+ await post(`/deploy/solutions/${solution_id}/github/patch`, {
1784
+ path: "solution.json",
1785
+ content: JSON.stringify(sol, null, 2),
1786
+ message: `Add skill "${skill_id}" to solution topology`,
1787
+ }, sid, { timeoutMs: 30_000 });
1788
+ phases.push({ phase: "solution_topology", status: "done", added: skill_id });
1789
+ } catch (err) {
1790
+ // Non-fatal: skill.json was written, topology can be fixed manually
1791
+ phases.push({ phase: "solution_topology", status: "warning", error: err.message });
1792
+ console.warn(`[ateam_patch] Failed to add ${skill_id} to solution topology: ${err.message}`);
1793
+ }
1794
+ }
1795
+
1796
+ // Phase 4: Redeploy from GitHub (extended timeout — deploys can take 60-120s)
1797
+ // IMPORTANT: if redeploy times out or fails, we return ok:true with a warning
1798
+ // because the patch IS saved to GitHub — it's not lost. The agent can retry
1799
+ // the redeploy with ateam_redeploy(solution_id, skill_id).
1734
1800
  let redeployResult;
1735
1801
  try {
1736
1802
  if (target === "skill" && skill_id) {
1737
- redeployResult = await post(`/deploy/solutions/${solution_id}/skills/${skill_id}/redeploy`, {}, sid);
1803
+ redeployResult = await post(`/deploy/solutions/${solution_id}/skills/${skill_id}/redeploy`, {}, sid, { timeoutMs: 180_000 });
1738
1804
  } else {
1739
- redeployResult = await post(`/deploy/solutions/${solution_id}/redeploy`, {}, sid);
1805
+ redeployResult = await post(`/deploy/solutions/${solution_id}/redeploy`, {}, sid, { timeoutMs: 180_000 });
1740
1806
  }
1741
1807
  phases.push({ phase: "redeploy", status: "done" });
1742
1808
  } catch (err) {
1743
- return {
1744
- ok: false,
1745
- phase: "redeploy",
1746
- phases,
1747
- error: err.message,
1748
- message: "Patch saved to GitHub but redeploy failed. Try ateam_redeploy manually.",
1749
- };
1809
+ // Partial success: patch is saved to GitHub, only redeploy failed.
1810
+ // Return ok:true so the agent doesn't think the patch was lost.
1811
+ phases.push({ phase: "redeploy", status: "timeout_or_error", error: err.message });
1812
+ console.warn(`[ateam_patch] Redeploy failed after successful patch: ${err.message}`);
1750
1813
  }
1751
1814
 
1752
1815
  // Phase 3: Optional re-test
@@ -1767,16 +1830,19 @@ const handlers = {
1767
1830
  }
1768
1831
  }
1769
1832
 
1770
- // Phase 4: Auto-push to main branch (non-blocking)
1833
+ const redeployOk = phases.some(p => p.phase === "redeploy" && p.status === "done");
1771
1834
  return {
1772
1835
  ok: true,
1773
1836
  solution_id,
1774
1837
  branch: 'main',
1775
1838
  phases,
1776
1839
  patched: patched,
1777
- redeploy: redeployResult,
1840
+ ...(isNewSkill && { created_skill: skill_id }),
1841
+ ...(redeployResult && { redeploy: redeployResult }),
1778
1842
  ...(test_result && { test_result }),
1779
- _status: '✅ Patched on GitHub + redeployed.',
1843
+ _status: redeployOk
1844
+ ? '✅ Patched on GitHub + redeployed.'
1845
+ : '⚠️ Patched on GitHub ✅ but redeploy timed out. Run: ateam_redeploy(solution_id' + (skill_id ? `, skill_id: "${skill_id}"` : '') + ')',
1780
1846
  _next: 'Create a checkpoint before making more changes: ateam_github_promote(solution_id)',
1781
1847
  };
1782
1848
  },