@ateam-ai/mcp 0.4.3 → 0.4.5

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
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/api.js CHANGED
@@ -378,10 +378,10 @@ function formatError(method, path, status, body) {
378
378
  "Versioned connector-code changes (edit, push, promote, deploy-from-repo) need a",
379
379
  "GitHub repo, and this tenant hasn't connected one yet.",
380
380
  "",
381
- "Connect it once (takes ~30s):",
382
- " 1. Open Tenant Admin → GitHub (https://app.ateam-ai.com → pick your tenant → GitHub).",
383
- " 2. Click \"Connect GitHub\" and approve the A-Team GitHub App.",
384
- " 3. Retry this step — the repo is auto-created on the next deploy.",
381
+ " Open this guide and follow the 3 steps: https://mcp.ateam-ai.com/connect-github",
382
+ "",
383
+ "In short: Tenant Admin → GitHub → \"Connect GitHub\", approve the App, then retry.",
384
+ "The repo is auto-created on the next deploy.",
385
385
  "",
386
386
  "No GitHub yet? Skill/solution DEFINITION edits still work without a repo via",
387
387
  "ateam_patch(..., source:\"local\"). Only connector CODE iteration needs GitHub.",
package/src/http.js CHANGED
@@ -29,6 +29,7 @@ import {
29
29
  bindSessionBearer, getAuthOverride,
30
30
  } from "./api.js";
31
31
  import { mountOAuth } from "./oauth.js";
32
+ import { connectGithubPage } from "./pages.js";
32
33
 
33
34
  // Active sessions
34
35
  const transports = {};
@@ -226,6 +227,12 @@ export function startHttpServer(port = 3100) {
226
227
  res.redirect("https://app.ateam-ai.com/builder/?show=api-key");
227
228
  });
228
229
 
230
+ // ─── Connect GitHub — user-facing guide an agent links to on
231
+ // github_not_connected (see formatError in api.js). ──
232
+ app.get("/connect-github", (_req, res) => {
233
+ res.type("html").send(connectGithubPage());
234
+ });
235
+
229
236
  // ─── MCP POST — handle tool calls + initialize ───────────────
230
237
  // Mounted at both "/" and "/mcp" for Claude.ai compatibility
231
238
  const mcpPost = async (req, res) => {
package/src/pages.js ADDED
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Static help pages served by the ateam-mcp HTTP server.
3
+ *
4
+ * These are user-facing landing pages an agent can link to from a tool result
5
+ * (e.g. the github_not_connected guide). Self-contained HTML, no external
6
+ * assets — matches the dark card style of the OAuth authorize page.
7
+ */
8
+
9
+ const APP_URL = process.env.ATEAM_APP_URL || "https://app.ateam-ai.com";
10
+
11
+ function shell(title, body) {
12
+ return `<!DOCTYPE html>
13
+ <html lang="en">
14
+ <head>
15
+ <meta charset="utf-8">
16
+ <meta name="viewport" content="width=device-width, initial-scale=1">
17
+ <title>${title} — A-Team</title>
18
+ <style>
19
+ * { box-sizing: border-box; margin: 0; padding: 0; }
20
+ body {
21
+ font-family: system-ui, -apple-system, sans-serif;
22
+ background: #0a0a0a; color: #e5e5e5;
23
+ display: flex; align-items: center; justify-content: center;
24
+ min-height: 100vh; padding: 20px; line-height: 1.55;
25
+ }
26
+ .card {
27
+ background: #171717; border: 1px solid #262626;
28
+ border-radius: 14px; padding: 34px; max-width: 560px; width: 100%;
29
+ }
30
+ .logo { font-size: 22px; font-weight: 700; margin-bottom: 4px; }
31
+ h1 { font-size: 21px; font-weight: 650; margin: 14px 0 6px; }
32
+ .lead { color: #a3a3a3; font-size: 15px; margin-bottom: 22px; }
33
+ ol { margin: 0 0 22px; padding-left: 0; list-style: none; counter-reset: step; }
34
+ li { position: relative; padding: 12px 0 12px 44px; border-top: 1px solid #222; counter-increment: step; }
35
+ li:first-child { border-top: none; }
36
+ li::before {
37
+ content: counter(step); position: absolute; left: 0; top: 12px;
38
+ width: 28px; height: 28px; border-radius: 50%;
39
+ background: #1e3a5f; color: #93c5fd; font-weight: 700; font-size: 14px;
40
+ display: flex; align-items: center; justify-content: center;
41
+ }
42
+ li b { color: #fff; font-weight: 600; }
43
+ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
44
+ background: #0a0a0a; border: 1px solid #333; border-radius: 5px;
45
+ padding: 1px 6px; font-size: 13px; color: #c4b5fd; }
46
+ .btn {
47
+ display: inline-block; background: #2563eb; color: #fff;
48
+ padding: 11px 20px; border-radius: 9px; font-size: 15px; font-weight: 600;
49
+ text-decoration: none;
50
+ }
51
+ .btn:hover { background: #1d4ed8; }
52
+ .note { margin-top: 20px; font-size: 13px; color: #737373; }
53
+ .note code { color: #9ca3af; }
54
+ a { color: #60a5fa; }
55
+ </style>
56
+ </head>
57
+ <body><div class="card">${body}</div></body>
58
+ </html>`;
59
+ }
60
+
61
+ export function connectGithubPage() {
62
+ return shell("Connect GitHub", `
63
+ <div class="logo">A-Team</div>
64
+ <h1>Connect GitHub to keep iterating</h1>
65
+ <div class="lead">
66
+ Editing, versioning, or promoting <b>connector code</b> needs a Git repo.
67
+ Connect your GitHub once — A-Team creates and manages the repo for you, and
68
+ every deploy is versioned from then on.
69
+ </div>
70
+ <ol>
71
+ <li>Open <b>Tenant Admin → GitHub</b> in the A-Team app (pick your tenant, then the GitHub tab).</li>
72
+ <li>Click <b>Connect GitHub</b> and approve the A-Team GitHub App for your account.</li>
73
+ <li>Go back to your agent and <b>retry</b> — the repo is auto-created on the next deploy.</li>
74
+ </ol>
75
+ <a class="btn" href="${APP_URL}" target="_blank" rel="noopener">Open the A-Team app →</a>
76
+ <div class="note">
77
+ Not ready for GitHub? Skill and solution <b>definition</b> edits still work
78
+ without a repo via <code>ateam_patch(..., source:"local")</code>. Only
79
+ connector <b>code</b> iteration needs GitHub.
80
+ </div>
81
+ `);
82
+ }
package/src/tools.js CHANGED
@@ -2847,7 +2847,17 @@ const handlers = {
2847
2847
 
2848
2848
  // Dry-run: return diff + would-be after-state without writing to GitHub
2849
2849
  // or redeploying. Lets an agent preview any destructive-looking edit.
2850
+ // would_write mirrors the EXACT persistence request the real run makes
2851
+ // (method/endpoint/body key) so create-vs-update routing bugs surface in
2852
+ // dry-run instead of only on the real write.
2850
2853
  if (dry_run) {
2854
+ const would_write = isLocal
2855
+ ? (target === "skill" && skill_id && isNewSkill
2856
+ ? { method: "POST", endpoint: `/deploy/solutions/${solution_id}/skills`, body_key: "skill", creates: true }
2857
+ : target === "skill" && skill_id
2858
+ ? { method: "PATCH", endpoint: `/deploy/solutions/${solution_id}/skills/${encodeURIComponent(skill_id)}`, body_key: "updates" }
2859
+ : { method: "PATCH", endpoint: `/deploy/solutions/${solution_id}`, body_key: "state_update" })
2860
+ : { method: "POST", endpoint: `/deploy/solutions/${solution_id}/github/patch`, body_key: "content" };
2851
2861
  return {
2852
2862
  ok: true,
2853
2863
  dry_run: true,
@@ -2857,6 +2867,7 @@ const handlers = {
2857
2867
  phases,
2858
2868
  _diff,
2859
2869
  after_state: patched,
2870
+ would_write,
2860
2871
  would_write_bytes: JSON.stringify(patched, null, 2).length,
2861
2872
  hint: "No changes applied. Remove dry_run:true to commit + redeploy.",
2862
2873
  };
@@ -2867,14 +2878,27 @@ const handlers = {
2867
2878
  const patchKeys = Object.keys(updates || {});
2868
2879
  const message = `Patch: ${target}${skill_id ? ` ${skill_id}` : ""} — ${patchKeys.join(", ")}`;
2869
2880
  if (isLocal) {
2870
- // Write the FULL patched object to the Builder store. Top-level keys are
2871
- // replaced (removals honored) the client-side merge above already
2872
- // resolved _push/_delete/_update, so we send the resolved object.
2873
- const endpoint = (target === "skill" && skill_id)
2874
- ? `/deploy/solutions/${solution_id}/skills/${encodeURIComponent(skill_id)}`
2875
- : `/deploy/solutions/${solution_id}`;
2876
- await patch(endpoint, { state_update: patched }, sid, { timeoutMs: 30_000 });
2877
- phases.push({ phase: "local_write", status: "done" });
2881
+ // Write the FULL patched object to the Builder store. The client-side
2882
+ // merge above already resolved _push/_delete/_update, so we send the
2883
+ // resolved object. THREE distinct Builder routes, each with its own
2884
+ // body contract (mismatching them 400s):
2885
+ // • NEW skill → POST /deploy/solutions/:id/skills { skill }
2886
+ // (creates via the Builder, applies the full definition, and
2887
+ // pushes the topology skills[] entry the PATCH route can't
2888
+ // create: it 404s on resolveSkillId / 400s "Updates object is
2889
+ // required". This was the japanese-tutor repo-less bug.)
2890
+ // • EXISTING skill → PATCH …/skills/:skillId { updates }
2891
+ // • Solution → PATCH /deploy/solutions/:id { state_update }
2892
+ if (target === "skill" && skill_id && isNewSkill) {
2893
+ await post(`/deploy/solutions/${solution_id}/skills`, { skill: patched }, sid, { timeoutMs: 30_000 });
2894
+ phases.push({ phase: "local_write", status: "done", created: true });
2895
+ } else if (target === "skill" && skill_id) {
2896
+ await patch(`/deploy/solutions/${solution_id}/skills/${encodeURIComponent(skill_id)}`, { updates: patched }, sid, { timeoutMs: 30_000 });
2897
+ phases.push({ phase: "local_write", status: "done" });
2898
+ } else {
2899
+ await patch(`/deploy/solutions/${solution_id}`, { state_update: patched }, sid, { timeoutMs: 30_000 });
2900
+ phases.push({ phase: "local_write", status: "done" });
2901
+ }
2878
2902
  } else {
2879
2903
  await post(`/deploy/solutions/${solution_id}/github/patch`, {
2880
2904
  path: filePath,