@ateam-ai/mcp 0.3.5 → 0.3.7

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 +104 -35
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
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
@@ -124,14 +124,18 @@ export const tools = [
124
124
  inputSchema: {
125
125
  type: "object",
126
126
  properties: {
127
+ solution_id: {
128
+ type: "string",
129
+ description: "The solution ID. Use this INSTEAD of passing the full solution object — the solution definition is auto-pulled from GitHub. Required if solution object is omitted.",
130
+ },
127
131
  solution: {
128
132
  type: "object",
129
- description: "Solution architecture identity, grants, handoffs, routing",
133
+ description: "Full solution definition. Required on first deploy. After first deploy, just pass solution_id instead — everything is auto-pulled from GitHub.",
130
134
  },
131
135
  skills: {
132
136
  type: "array",
133
137
  items: { type: "object" },
134
- description: "Array of full skill definitions",
138
+ description: "Optional after first deploy: skill definitions. If omitted, auto-pulled from GitHub repo (skills/{id}/skill.json).",
135
139
  },
136
140
  connectors: {
137
141
  type: "array",
@@ -155,7 +159,7 @@ export const tools = [
155
159
  description: "Optional: which skill to test (defaults to the first skill).",
156
160
  },
157
161
  },
158
- required: ["solution", "skills"],
162
+ required: [],
159
163
  },
160
164
  },
161
165
  {
@@ -1291,7 +1295,13 @@ const handlers = {
1291
1295
  // Validates → Deploys → Health-checks → Optionally tests
1292
1296
  // One call replaces: validate_solution + deploy_solution + get_solution(health)
1293
1297
 
1294
- ateam_build_and_run: async ({ solution, skills, connectors, mcp_store, github, test_message, test_skill_id }, sid) => {
1298
+ ateam_build_and_run: async ({ solution_id: solIdArg, solution: solutionArg, skills, connectors, mcp_store, github, test_message, test_skill_id }, sid) => {
1299
+ let solution = solutionArg;
1300
+ // If only solution_id passed (no full solution), we'll pull from GitHub
1301
+ const solutionId = solution?.id || solIdArg;
1302
+ if (!solutionId) {
1303
+ return { ok: false, phase: "pre_check", error: "Provide either solution (object) or solution_id (string)." };
1304
+ }
1295
1305
  const phases = [];
1296
1306
 
1297
1307
  // Guard: reject large mcp_store — agent should use github_patch instead
@@ -1314,13 +1324,13 @@ const handlers = {
1314
1324
  }
1315
1325
  }
1316
1326
 
1317
- // Phase 0: Auto-detect GitHub repo — if no mcp_store passed and repo exists, pull from GitHub automatically
1327
+ // Phase 0: Auto-detect GitHub repo — if no mcp_store passed and repo exists, pull bundle from GitHub
1318
1328
  let effectiveMcpStore = mcp_store;
1329
+ let effectiveSkills = skills;
1319
1330
  if (!mcp_store) {
1320
1331
  try {
1321
- const ghStatus = await get(`/deploy/solutions/${solution.id}/github/status`, sid);
1332
+ const ghStatus = await get(`/deploy/solutions/${solutionId}/github/status`, sid);
1322
1333
  if (ghStatus?.repo_url) {
1323
- // Repo exists — auto-pull from GitHub
1324
1334
  github = true;
1325
1335
  }
1326
1336
  } catch { /* no repo — first deploy, mcp_store expected */ }
@@ -1328,24 +1338,33 @@ const handlers = {
1328
1338
  if (github && !mcp_store) {
1329
1339
  try {
1330
1340
  const pullResult = await post(
1331
- `/deploy/solutions/${solution.id}/github/pull-connectors`,
1341
+ `/deploy/solutions/${solutionId}/github/pull-bundle`,
1332
1342
  {},
1333
1343
  sid,
1334
- { timeoutMs: 30_000 },
1344
+ { timeoutMs: 60_000 },
1335
1345
  );
1336
1346
  if (!pullResult.ok) {
1337
1347
  return {
1338
1348
  ok: false,
1339
1349
  phase: "github_pull",
1340
- error: pullResult.error || "Failed to pull connectors from GitHub",
1350
+ error: pullResult.error || "Failed to pull bundle from GitHub",
1341
1351
  hint: pullResult.hint || "Deploy the solution first (with mcp_store) to auto-create the GitHub repo.",
1342
- message: "Cannot pull connector code from GitHub. The repo may not exist yet — deploy with mcp_store first.",
1352
+ message: "Cannot pull from GitHub. The repo may not exist yet — deploy with mcp_store first.",
1343
1353
  };
1344
1354
  }
1345
- effectiveMcpStore = pullResult.mcp_store;
1355
+ effectiveMcpStore = pullResult.mcp_store || {};
1356
+ // Use solution from GitHub if not passed inline
1357
+ if (!solution && pullResult.solution) {
1358
+ solution = pullResult.solution;
1359
+ }
1360
+ // Use skills from GitHub if not passed inline
1361
+ if (!effectiveSkills?.length && pullResult.skills?.length) {
1362
+ effectiveSkills = pullResult.skills;
1363
+ }
1346
1364
  phases.push({
1347
1365
  phase: "github_pull",
1348
1366
  status: "done",
1367
+ skills_found: pullResult.skills_found || 0,
1349
1368
  connectors_found: pullResult.connectors_found || 0,
1350
1369
  files_loaded: pullResult.files_loaded || 0,
1351
1370
  });
@@ -1354,15 +1373,35 @@ const handlers = {
1354
1373
  ok: false,
1355
1374
  phase: "github_pull",
1356
1375
  error: err.message,
1357
- message: "Failed to pull connector code from GitHub. The repo may not exist yet — deploy with mcp_store first.",
1376
+ message: "Failed to pull from GitHub. The repo may not exist yet — deploy with mcp_store first.",
1358
1377
  };
1359
1378
  }
1360
1379
  }
1361
1380
 
1381
+ // Guard: solution required (either inline or from GitHub)
1382
+ if (!solution) {
1383
+ return {
1384
+ ok: false,
1385
+ phase: "pre_check",
1386
+ error: "No solution provided and none found in GitHub repo.",
1387
+ message: "Pass solution inline or ensure solution.json exists in the GitHub repo.",
1388
+ };
1389
+ }
1390
+
1391
+ // Guard: skills required (either inline or from GitHub)
1392
+ if (!effectiveSkills?.length) {
1393
+ return {
1394
+ ok: false,
1395
+ phase: "pre_check",
1396
+ error: "No skills provided and none found in GitHub repo.",
1397
+ message: "Pass skills inline or ensure they exist in the GitHub repo (skills/{id}/skill.json).",
1398
+ };
1399
+ }
1400
+
1362
1401
  // Phase 1: Validate
1363
1402
  let validation;
1364
1403
  try {
1365
- validation = await post("/validate/solution", { solution, skills, connectors, mcp_store: effectiveMcpStore }, sid, { timeoutMs: 120_000 });
1404
+ validation = await post("/validate/solution", { solution, skills: effectiveSkills, connectors, mcp_store: effectiveMcpStore }, sid, { timeoutMs: 120_000 });
1366
1405
  phases.push({ phase: "validate", status: "done" });
1367
1406
  } catch (err) {
1368
1407
  return {
@@ -1388,7 +1427,7 @@ const handlers = {
1388
1427
  // Phase 2: Deploy
1389
1428
  let deploy;
1390
1429
  try {
1391
- deploy = await post("/deploy/solution", { solution, skills, connectors, mcp_store: effectiveMcpStore }, sid, { timeoutMs: 300_000, retries: 2 });
1430
+ deploy = await post("/deploy/solution", { solution, skills: effectiveSkills, connectors, mcp_store: effectiveMcpStore }, sid, { timeoutMs: 300_000, retries: 2 });
1392
1431
  phases.push({ phase: "deploy", status: deploy.ok ? "done" : "failed" });
1393
1432
  } catch (err) {
1394
1433
  return {
@@ -1412,11 +1451,35 @@ const handlers = {
1412
1451
  };
1413
1452
  }
1414
1453
 
1454
+ // Phase 2.5: Restart connectors that have source code (upload triggers stop+start)
1455
+ if (effectiveMcpStore && Object.keys(effectiveMcpStore).length > 0) {
1456
+ const connectorResults = [];
1457
+ for (const [connId, files] of Object.entries(effectiveMcpStore)) {
1458
+ if (!Array.isArray(files) || files.length === 0) continue;
1459
+ try {
1460
+ const uploadResult = await post(
1461
+ `/deploy/solutions/${solutionId}/connectors/${connId}/upload`,
1462
+ { files },
1463
+ sid,
1464
+ { timeoutMs: 120_000 },
1465
+ );
1466
+ connectorResults.push({ id: connId, ok: true, tools: uploadResult.tools || 0 });
1467
+ } catch (err) {
1468
+ connectorResults.push({ id: connId, ok: false, error: err.message });
1469
+ }
1470
+ }
1471
+ phases.push({
1472
+ phase: "connector_restart",
1473
+ status: connectorResults.every(r => r.ok) ? "done" : "partial",
1474
+ connectors: connectorResults,
1475
+ });
1476
+ }
1477
+
1415
1478
  // Phase 3: Health check (with brief wait for propagation)
1416
1479
  let health;
1417
1480
  try {
1418
1481
  await sleep(2000);
1419
- health = await get(`/deploy/solutions/${solution.id}/health`, sid);
1482
+ health = await get(`/deploy/solutions/${solutionId}/health`, sid);
1420
1483
  phases.push({ phase: "health", status: "done" });
1421
1484
  } catch (err) {
1422
1485
  health = { error: err.message };
@@ -1426,11 +1489,11 @@ const handlers = {
1426
1489
  // Phase 4: Warm test (optional)
1427
1490
  let test_result;
1428
1491
  if (test_message) {
1429
- const skillId = test_skill_id || skills?.[0]?.id;
1492
+ const skillId = test_skill_id || effectiveSkills?.[0]?.id;
1430
1493
  if (skillId) {
1431
1494
  try {
1432
1495
  test_result = await post(
1433
- `/deploy/solutions/${solution.id}/skills/${skillId}/test`,
1496
+ `/deploy/solutions/${solutionId}/skills/${skillId}/test`,
1434
1497
  { message: test_message },
1435
1498
  sid,
1436
1499
  { timeoutMs: 90_000 },
@@ -1443,28 +1506,34 @@ const handlers = {
1443
1506
  }
1444
1507
  }
1445
1508
 
1446
- // Phase 5: GitHub push (auto non-blocking, failures don't fail the deploy)
1509
+ // Phase 5: GitHub push (skip if we just pulled from GitHub — don't overwrite source of truth)
1447
1510
  let github_result;
1448
- try {
1449
- github_result = await post(
1450
- `/deploy/solutions/${solution.id}/github/push`,
1451
- { message: `Deploy: ${solution.name || solution.id}` },
1452
- sid,
1453
- { timeoutMs: 60_000 },
1454
- );
1455
- phases.push({
1456
- phase: "github",
1457
- status: github_result.skipped ? "skipped" : "done",
1458
- ...(github_result.repo_url && { repo_url: github_result.repo_url }),
1459
- });
1460
- } catch (err) {
1461
- github_result = { error: err.message };
1462
- phases.push({ phase: "github", status: "error", error: err.message });
1511
+ if (github) {
1512
+ // We pulled from GitHub → GitHub IS the source of truth. Don't push stale Core state back.
1513
+ github_result = { skipped: true, reason: 'Deployed from GitHub — skipping push-back to avoid overwriting source of truth.' };
1514
+ phases.push({ phase: "github", status: "skipped", reason: "pulled_from_github" });
1515
+ } else {
1516
+ try {
1517
+ github_result = await post(
1518
+ `/deploy/solutions/${solutionId}/github/push`,
1519
+ { message: `Deploy: ${solution.name || solutionId}` },
1520
+ sid,
1521
+ { timeoutMs: 60_000 },
1522
+ );
1523
+ phases.push({
1524
+ phase: "github",
1525
+ status: github_result.skipped ? "skipped" : "done",
1526
+ ...(github_result.repo_url && { repo_url: github_result.repo_url }),
1527
+ });
1528
+ } catch (err) {
1529
+ github_result = { error: err.message };
1530
+ phases.push({ phase: "github", status: "error", error: err.message });
1531
+ }
1463
1532
  }
1464
1533
 
1465
1534
  return {
1466
1535
  ok: true,
1467
- solution_id: solution.id,
1536
+ solution_id: solutionId,
1468
1537
  branch: 'main',
1469
1538
  phases,
1470
1539
  deploy: {