@ateam-ai/mcp 0.4.13 → 0.4.15

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 +45 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.4.13",
3
+ "version": "0.4.15",
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
@@ -2017,6 +2017,32 @@ export default {
2017
2017
  });
2018
2018
  }
2019
2019
 
2020
+ // Emit a manifest.json with the render block the platform requires. A plugin
2021
+ // is only DISCOVERABLE + RENDERABLE if it appears in the connector's
2022
+ // ui.listPlugins / ui.getPlugin output WITH a render.{ mode, iframeUrl?,
2023
+ // reactNative? } — dropping the HTML/TSX files alone is NOT enough. This
2024
+ // manifest is the source of truth for that block; connectors whose
2025
+ // ui.listPlugins is generated from ui-dist/<plugin>/manifest.json pick it up
2026
+ // automatically, and for connectors with a HARDCODED plugin list (e.g.
2027
+ // personal-assistant-ui-mcp) copy this render block into their ui.getPlugin.
2028
+ const mode = k === "iframe" ? "iframe" : k === "rn" ? "react-native" : "adaptive";
2029
+ const render = { mode };
2030
+ if (k === "iframe" || k === "adaptive") render.iframeUrl = `/ui/${pluginName}/index.html`;
2031
+ if (k === "rn" || k === "adaptive") render.reactNative = { component: pluginName };
2032
+ const prettyName = pluginName.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
2033
+ files.push({
2034
+ path: `ui-dist/${pluginName}/manifest.json`,
2035
+ content: JSON.stringify({
2036
+ id: pluginName,
2037
+ name: prettyName,
2038
+ version: "1.0.0",
2039
+ description: `${prettyName} plugin — replace with your real description.`,
2040
+ render,
2041
+ channels: ["command"],
2042
+ capabilities: { commands: [] },
2043
+ }, null, 2) + "\n",
2044
+ });
2045
+
2020
2046
  return files;
2021
2047
  }
2022
2048
 
@@ -2079,10 +2105,25 @@ const handlers = {
2079
2105
  { step: 2, action: "Build & Run", description: "Define your solution + skills + connector code, then validate, deploy, and health-check in one call. Include mcp_store with connector source code on the first deploy.", tools: ["ateam_build_and_run"] },
2080
2106
  { step: 3, action: "Version", description: "Every deploy auto-pushes to main on GitHub. The repo (tenant--solution-id) is the source of truth for connector code.", tools: ["ateam_github_status", "ateam_github_log"] },
2081
2107
  { step: 4, action: "Iterate", description: "Edit connector code ONE FILE AT A TIME via ateam_github_patch, then redeploy with ateam_build_and_run (auto-pulls from GitHub). NEVER re-pass all connector code inline after first deploy. For skill definitions, use ateam_patch.", tools: ["ateam_github_patch", "ateam_build_and_run", "ateam_patch"] },
2082
- { step: 5, action: "Test & Debug", description: "Test with ateam_conversation (auto-routes, supports multi-turn with actor_id for confirmations). Use ateam_test_pipeline for intent debugging, ateam_test_voice for voice. Diagnose with logs and metrics.", tools: ["ateam_conversation", "ateam_test_pipeline", "ateam_test_skill", "ateam_test_voice", "ateam_get_execution_logs", "ateam_get_metrics"] },
2108
+ { step: 5, action: "Test & Debug", description: "Chat with the solution via ateam_conversation (auto-routes; multi-turn via actor_id). It is ASYNC — see conversation_flow below: kick off → get chain_id → poll ateam_chain_status until chain_done → read the reply. Use ateam_test_pipeline for intent debugging, ateam_test_voice for voice. Diagnose with logs and metrics.", tools: ["ateam_conversation", "ateam_chain_status", "ateam_get_chain", "ateam_test_pipeline", "ateam_test_skill", "ateam_test_voice", "ateam_get_execution_logs", "ateam_get_metrics"] },
2083
2109
  { step: 6, action: "Checkpoint", description: "When solution is in a good state, create a checkpoint (safe point). You can rollback to any checkpoint if something breaks.", tools: ["ateam_github_promote", "ateam_github_list_versions"] },
2084
2110
  ],
2085
2111
  },
2112
+ conversation_flow: {
2113
+ _important: "ateam_conversation is ASYNC and CHAIN-based. A conversation runs across handoffs + askAnySkill subcalls for possibly minutes — a synchronous wait would hit the 100s edge timeout (524). ALWAYS poll by CHAIN, NEVER by a single job (a job can terminate while the chain is still active).",
2114
+ steps: [
2115
+ "1. KICK OFF — ateam_conversation(solution_id, message[, actor_id]) → returns { chain_id, actor_id } immediately. The reply is NOT here.",
2116
+ "2. POLL (chip-quick, cheap) — loop ateam_chain_status(chain_id) every ~2s. It returns the whole-chain aggregate { chain_status, chain_done, pending_question, result }. Stop when chain_done === true, OR when pending_question is set (the assistant is asking the user something — answer via step 4).",
2117
+ "3. READ THE REPLY — when chain_done, use result. For full per-job detail / the routed worker's output, call ateam_get_chain(chain_id) ONCE (it returns the entire chain tree: every job + every tool step). Do NOT poll get_chain in a loop — it's heavy.",
2118
+ "4. CONTINUE THE THREAD — reply / next turn: ateam_conversation(solution_id, message, actor_id: <same actor_id>). New chain, same conversation context. Repeat from step 2.",
2119
+ ],
2120
+ example: {
2121
+ kickoff: 'ateam_conversation(solution_id: "ada", message: "log 3 glasses of water") → { chain_id: "job_ab12", actor_id: "test_x" }',
2122
+ poll: 'ateam_chain_status(chain_id: "job_ab12") → { chain_status: "running", chain_done: false } … repeat … → { chain_status: "completed", chain_done: true, result: "…" }',
2123
+ full_tree: 'ateam_get_chain(chain_id: "job_ab12") → { chainJobs: [ {jobId, skill, status, relation, depth} … ], executionSteps: [ … ] }',
2124
+ continue: 'ateam_conversation(solution_id: "ada", message: "yes", actor_id: "test_x")',
2125
+ },
2126
+ },
2086
2127
  branching: {
2087
2128
  _important: "Single-branch model: ALL changes go directly to 'main'. Use checkpoints (safe-* tags) as safe rollback points.",
2088
2129
  main: "The only branch. All deploys, patches, and github_patches commit here automatically. This IS the live running system.",
@@ -3884,8 +3925,9 @@ const handlers = {
3884
3925
  k === "iframe" || k === "adaptive"
3885
3926
  ? `Edit ui-dist/${plugin_name}/index.html — replace the placeholder UI.`
3886
3927
  : null,
3887
- `Phase 5 auto-discovery will register the plugin at next deploy.`,
3888
- `Optional: drop a manifest.json next to the source for custom commands/capabilities.`,
3928
+ `A manifest.json (with the required render block) was written to ui-dist/${plugin_name}/manifest.json.`,
3929
+ `⚠️ REQUIRED to render: the plugin must appear in this connector's ui.listPlugins / ui.getPlugin output WITH that render block. Dropping the files alone does NOT register it. If the connector has a HARDCODED plugin list (e.g. personal-assistant-ui-mcp: UI_PLUGINS[] + PLUGIN_MANIFESTS{} in server.js), add this plugin there — copy the render block from the manifest.json. Verify with ateam_get_solution(solution_id, "connectors_health") or ateam_get_widget_catalog after deploy.`,
3930
+ `Then declare it at solution level (ui_plugins[]) so a skill can open it via sys.focusUiPlugin — see ateam_get_spec(topic:"widgets").`,
3889
3931
  ].filter(Boolean),
3890
3932
  };
3891
3933
  },