@ateam-ai/mcp 0.3.21 → 0.3.23
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 +132 -16
package/package.json
CHANGED
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
|
|
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",
|
|
@@ -1244,6 +1246,56 @@ const handlers = {
|
|
|
1244
1246
|
security: "https://ateam-ai.com/#security",
|
|
1245
1247
|
engine: "https://ateam-ai.com/#engine",
|
|
1246
1248
|
},
|
|
1249
|
+
platform_connectors: {
|
|
1250
|
+
_note: "Shared infrastructure MCPs available to all solutions. Reference by id in your solution's `platform_connectors` array; tools are automatically merged into every skill's tool catalog (no bridge needed). Do NOT bundle their source in mcp_store — they run as fixed Docker services on ADAS Core.",
|
|
1251
|
+
available: [
|
|
1252
|
+
{
|
|
1253
|
+
id: "memory-mcp",
|
|
1254
|
+
name: "Memory Engine",
|
|
1255
|
+
purpose: "Long-term memory + ephemeral context, per-tenant per-actor",
|
|
1256
|
+
tool_prefixes: ["memory.", "context."],
|
|
1257
|
+
typical_use: "Store user preferences/facts, recall rules, persist working context across conversations",
|
|
1258
|
+
},
|
|
1259
|
+
{
|
|
1260
|
+
id: "docs-index-mcp",
|
|
1261
|
+
name: "Docs Index",
|
|
1262
|
+
purpose: "Source-agnostic document corpus retrieval (chunking, embeddings, cosine search)",
|
|
1263
|
+
tool_prefixes: ["docs.corpus.", "docs.ingest.", "docs.search", "docs.file.", "docs.sync.", "docs.stats"],
|
|
1264
|
+
typical_use: "Index documents from any source (Dropbox, Gmail attachments, uploaded files), answer questions with retrieved chunks + citations. Fed by source connectors (e.g. dropbox-mcp) that call docs.ingest.file.",
|
|
1265
|
+
},
|
|
1266
|
+
{
|
|
1267
|
+
id: "handoff-controller-mcp",
|
|
1268
|
+
name: "Handoff Controller",
|
|
1269
|
+
purpose: "Live conversation handoffs between skills in a multi-skill solution",
|
|
1270
|
+
tool_prefixes: ["handoff."],
|
|
1271
|
+
typical_use: "Pass a live conversation from one skill to another (e.g. identity-assurance → order-support), carrying grants",
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
id: "internal-comm-mcp",
|
|
1275
|
+
name: "Internal Communication",
|
|
1276
|
+
purpose: "Skill-to-skill messaging and voice replies",
|
|
1277
|
+
tool_prefixes: ["comm."],
|
|
1278
|
+
typical_use: "Async message between skills, or send a voice reply back through the Twilio channel",
|
|
1279
|
+
},
|
|
1280
|
+
{
|
|
1281
|
+
id: "browser-mcp",
|
|
1282
|
+
name: "Browser",
|
|
1283
|
+
purpose: "Headless Chromium automation (Playwright)",
|
|
1284
|
+
tool_prefixes: ["web."],
|
|
1285
|
+
typical_use: "Navigate, read, click, type, screenshot any public web page; scrape data for enrichment",
|
|
1286
|
+
},
|
|
1287
|
+
],
|
|
1288
|
+
how_to_use: {
|
|
1289
|
+
step_1: "Declare in solution: platform_connectors: [{ id: 'memory-mcp', required: true }]",
|
|
1290
|
+
step_2: "Tools become available in the skill's tool catalog automatically — no code to write, no bridge needed",
|
|
1291
|
+
step_3: "Reference tools in skill.tools[] with source.type='mcp_bridge', connection_id matching the connector id",
|
|
1292
|
+
},
|
|
1293
|
+
do_not: [
|
|
1294
|
+
"Do NOT include platform connector source code in mcp_store — they're managed by the platform, not by your solution",
|
|
1295
|
+
"Do NOT try to deploy a duplicate platform connector as a solution connector — use the platform one directly",
|
|
1296
|
+
"Do NOT build stdio bridge connectors for platform services — the platform auto-merges their tools",
|
|
1297
|
+
],
|
|
1298
|
+
},
|
|
1247
1299
|
critical_connector_rules: {
|
|
1248
1300
|
_note: "CRITICAL: Read this before writing ANY connector code. Violations are caught at deploy time and BLOCKED.",
|
|
1249
1301
|
transport: "A-Team connectors use STDIO transport — child processes communicating via stdin/stdout JSON-RPC.",
|
|
@@ -1659,11 +1711,12 @@ const handlers = {
|
|
|
1659
1711
|
|
|
1660
1712
|
ateam_patch: async ({ solution_id, target, skill_id, updates, test_message }, sid) => {
|
|
1661
1713
|
const phases = [];
|
|
1714
|
+
let isNewSkill = false;
|
|
1662
1715
|
|
|
1663
1716
|
// GitHub-first patch: read from GitHub → apply patch → write back → redeploy
|
|
1664
1717
|
// This ensures GitHub stays the single source of truth.
|
|
1665
1718
|
|
|
1666
|
-
// Phase 1: Read current state from GitHub
|
|
1719
|
+
// Phase 1: Read current state from GitHub (or create scaffold if new skill)
|
|
1667
1720
|
let current;
|
|
1668
1721
|
const filePath = target === "skill" && skill_id
|
|
1669
1722
|
? `skills/${skill_id}/skill.json`
|
|
@@ -1672,7 +1725,38 @@ const handlers = {
|
|
|
1672
1725
|
const readResult = await get(`/deploy/solutions/${solution_id}/github/read?path=${encodeURIComponent(filePath)}`, sid);
|
|
1673
1726
|
current = JSON.parse(readResult.content);
|
|
1674
1727
|
} catch (err) {
|
|
1675
|
-
|
|
1728
|
+
// If it's a skill that doesn't exist yet, create a default scaffold.
|
|
1729
|
+
// This lets agents use ateam_patch to both CREATE and UPDATE skills —
|
|
1730
|
+
// no separate "create" step needed.
|
|
1731
|
+
if (target === "skill" && skill_id) {
|
|
1732
|
+
console.log(`[ateam_patch] Skill "${skill_id}" not found on GitHub — creating new skill scaffold`);
|
|
1733
|
+
isNewSkill = true;
|
|
1734
|
+
current = {
|
|
1735
|
+
id: skill_id,
|
|
1736
|
+
name: skill_id.replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase()),
|
|
1737
|
+
description: "",
|
|
1738
|
+
version: "0.1.0",
|
|
1739
|
+
phase: "PROBLEM_DISCOVERY",
|
|
1740
|
+
connectors: [],
|
|
1741
|
+
problem: { statement: "", context: "", goals: [] },
|
|
1742
|
+
scenarios: [],
|
|
1743
|
+
role: { name: "", persona: "", goals: [], limitations: [], communication_style: { tone: "professional", verbosity: "concise" } },
|
|
1744
|
+
intents: { supported: [], thresholds: { accept: 0.8, clarify: 0.5, reject: 0.5 }, out_of_domain: { action: "redirect", message: "" } },
|
|
1745
|
+
tools: [],
|
|
1746
|
+
policy: { guardrails: { never: [], always: [] }, approvals: [], workflows: [], escalation: { enabled: false, conditions: [], target: "" } },
|
|
1747
|
+
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 } },
|
|
1748
|
+
access_policy: { rules: [{ tools: ["*"], effect: "allow" }] },
|
|
1749
|
+
grant_mappings: [],
|
|
1750
|
+
channels: [],
|
|
1751
|
+
conversation: [],
|
|
1752
|
+
triggers: [],
|
|
1753
|
+
meta_tools: [],
|
|
1754
|
+
glossary: {},
|
|
1755
|
+
};
|
|
1756
|
+
phases.push({ phase: "read", status: "created_scaffold", skill_id });
|
|
1757
|
+
} else {
|
|
1758
|
+
return { ok: false, phase: "read", error: `Failed to read ${filePath} from GitHub: ${err.message}` };
|
|
1759
|
+
}
|
|
1676
1760
|
}
|
|
1677
1761
|
|
|
1678
1762
|
// Phase 2: Apply patch in memory
|
|
@@ -1730,23 +1814,52 @@ const handlers = {
|
|
|
1730
1814
|
return { ok: false, phase: "github_write", error: `Patch applied but failed to write to GitHub: ${err.message}`, phases };
|
|
1731
1815
|
}
|
|
1732
1816
|
|
|
1733
|
-
// Phase
|
|
1817
|
+
// Phase 3b: If new skill, add it to solution.json topology (skills[], linked_skills)
|
|
1818
|
+
if (isNewSkill && skill_id) {
|
|
1819
|
+
try {
|
|
1820
|
+
const solRead = await get(`/deploy/solutions/${solution_id}/github/read?path=solution.json`, sid);
|
|
1821
|
+
const sol = JSON.parse(solRead.content);
|
|
1822
|
+
const skillEntry = { id: skill_id, name: patched.name || skill_id, role: "worker", description: patched.description || "", connectors: patched.connectors || [] };
|
|
1823
|
+
// Add to skills[] if not already present
|
|
1824
|
+
if (!sol.skills) sol.skills = [];
|
|
1825
|
+
if (!sol.skills.find(s => s.id === skill_id)) {
|
|
1826
|
+
sol.skills.push(skillEntry);
|
|
1827
|
+
}
|
|
1828
|
+
// Add to linked_skills if not already present
|
|
1829
|
+
if (!sol.linked_skills) sol.linked_skills = [];
|
|
1830
|
+
if (!sol.linked_skills.includes(skill_id)) {
|
|
1831
|
+
sol.linked_skills.push(skill_id);
|
|
1832
|
+
}
|
|
1833
|
+
await post(`/deploy/solutions/${solution_id}/github/patch`, {
|
|
1834
|
+
path: "solution.json",
|
|
1835
|
+
content: JSON.stringify(sol, null, 2),
|
|
1836
|
+
message: `Add skill "${skill_id}" to solution topology`,
|
|
1837
|
+
}, sid, { timeoutMs: 30_000 });
|
|
1838
|
+
phases.push({ phase: "solution_topology", status: "done", added: skill_id });
|
|
1839
|
+
} catch (err) {
|
|
1840
|
+
// Non-fatal: skill.json was written, topology can be fixed manually
|
|
1841
|
+
phases.push({ phase: "solution_topology", status: "warning", error: err.message });
|
|
1842
|
+
console.warn(`[ateam_patch] Failed to add ${skill_id} to solution topology: ${err.message}`);
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
// Phase 4: Redeploy from GitHub (extended timeout — deploys can take 60-120s)
|
|
1847
|
+
// IMPORTANT: if redeploy times out or fails, we return ok:true with a warning
|
|
1848
|
+
// because the patch IS saved to GitHub — it's not lost. The agent can retry
|
|
1849
|
+
// the redeploy with ateam_redeploy(solution_id, skill_id).
|
|
1734
1850
|
let redeployResult;
|
|
1735
1851
|
try {
|
|
1736
1852
|
if (target === "skill" && skill_id) {
|
|
1737
|
-
redeployResult = await post(`/deploy/solutions/${solution_id}/skills/${skill_id}/redeploy`, {}, sid);
|
|
1853
|
+
redeployResult = await post(`/deploy/solutions/${solution_id}/skills/${skill_id}/redeploy`, {}, sid, { timeoutMs: 180_000 });
|
|
1738
1854
|
} else {
|
|
1739
|
-
redeployResult = await post(`/deploy/solutions/${solution_id}/redeploy`, {}, sid);
|
|
1855
|
+
redeployResult = await post(`/deploy/solutions/${solution_id}/redeploy`, {}, sid, { timeoutMs: 180_000 });
|
|
1740
1856
|
}
|
|
1741
1857
|
phases.push({ phase: "redeploy", status: "done" });
|
|
1742
1858
|
} catch (err) {
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
error: err.message,
|
|
1748
|
-
message: "Patch saved to GitHub but redeploy failed. Try ateam_redeploy manually.",
|
|
1749
|
-
};
|
|
1859
|
+
// Partial success: patch is saved to GitHub, only redeploy failed.
|
|
1860
|
+
// Return ok:true so the agent doesn't think the patch was lost.
|
|
1861
|
+
phases.push({ phase: "redeploy", status: "timeout_or_error", error: err.message });
|
|
1862
|
+
console.warn(`[ateam_patch] Redeploy failed after successful patch: ${err.message}`);
|
|
1750
1863
|
}
|
|
1751
1864
|
|
|
1752
1865
|
// Phase 3: Optional re-test
|
|
@@ -1767,16 +1880,19 @@ const handlers = {
|
|
|
1767
1880
|
}
|
|
1768
1881
|
}
|
|
1769
1882
|
|
|
1770
|
-
|
|
1883
|
+
const redeployOk = phases.some(p => p.phase === "redeploy" && p.status === "done");
|
|
1771
1884
|
return {
|
|
1772
1885
|
ok: true,
|
|
1773
1886
|
solution_id,
|
|
1774
1887
|
branch: 'main',
|
|
1775
1888
|
phases,
|
|
1776
1889
|
patched: patched,
|
|
1777
|
-
|
|
1890
|
+
...(isNewSkill && { created_skill: skill_id }),
|
|
1891
|
+
...(redeployResult && { redeploy: redeployResult }),
|
|
1778
1892
|
...(test_result && { test_result }),
|
|
1779
|
-
_status:
|
|
1893
|
+
_status: redeployOk
|
|
1894
|
+
? '✅ Patched on GitHub + redeployed.'
|
|
1895
|
+
: '⚠️ Patched on GitHub ✅ but redeploy timed out. Run: ateam_redeploy(solution_id' + (skill_id ? `, skill_id: "${skill_id}"` : '') + ')',
|
|
1780
1896
|
_next: 'Create a checkpoint before making more changes: ateam_github_promote(solution_id)',
|
|
1781
1897
|
};
|
|
1782
1898
|
},
|