@ateam-ai/mcp 0.1.11 → 0.1.13

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/src/tools.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * A-Team MCP tool definitions and handlers.
3
- * 15 tools covering the full A-Team External Agent API + auth + bootstrap.
3
+ * 18 tools covering the full A-Team External Agent API + auth + bootstrap.
4
4
  */
5
5
 
6
6
  import {
@@ -120,7 +120,7 @@ export const tools = [
120
120
  {
121
121
  name: "ateam_deploy_solution",
122
122
  description:
123
- "Deploy a governed AI Team solution to A-Team Core — identity, connectors, skills. The Skill Builder auto-generates MCP servers from tool definitions. Used after defining system architecture. Always validate first using ateam_validate_solution. Requires authentication (call ateam_auth first if not using env vars).",
123
+ "Deploy a governed AI Team solution to A-Team Core — identity, connectors, skills. The Skill Builder auto-generates MCP servers from tool definitions. For connectors with UI or Node.js code, send SOURCE files only via mcp_store — the server runs npm install + npm run build automatically (like Vercel/Netlify). Never send dist/ or node_modules/. Always validate first using ateam_validate_solution. Requires authentication (call ateam_auth first if not using env vars).",
124
124
  inputSchema: {
125
125
  type: "object",
126
126
  properties: {
@@ -136,12 +136,12 @@ export const tools = [
136
136
  connectors: {
137
137
  type: "array",
138
138
  items: { type: "object" },
139
- description: "Array of connector metadata (id, name, transport, command, args)",
139
+ description: "Array of connector metadata (id, name, transport). command and args are OPTIONAL when mcp_store provides the code — the system auto-detects the entry point (server.js, index.js, package.json main, server.py) and runtime (node, python3). You can still provide explicit command/args to override auto-detection.",
140
140
  },
141
141
  mcp_store: {
142
142
  type: "object",
143
143
  description:
144
- "Optional: connector source code files. Key = connector id, value = array of {path, content}",
144
+ "Optional: connector source code files. Key = connector id, value = array of {path, content}. Send SOURCE files only (server.js, package.json, src/*.jsx, etc.) — the server runs npm install + npm run build automatically. Never include node_modules/ or dist/ folders. Entry point is auto-detected from the uploaded files.",
145
145
  },
146
146
  },
147
147
  required: ["solution", "skills"],
@@ -179,6 +179,35 @@ export const tools = [
179
179
  required: ["connector"],
180
180
  },
181
181
  },
182
+ {
183
+ name: "ateam_upload_connector_files",
184
+ description:
185
+ "Upload source files for a connector's MCP server. Use this INSTEAD of mcp_store in ateam_deploy_solution when the source code is too large to inline. Upload files first (one call per file or a few small files at a time), then deploy the solution without mcp_store, then redeploy. Files are staged and automatically included in the next deploy. Requires authentication.",
186
+ inputSchema: {
187
+ type: "object",
188
+ properties: {
189
+ connector_id: {
190
+ type: "string",
191
+ description: "The connector ID (must match the connector's id in the solution)",
192
+ },
193
+ files: {
194
+ type: "array",
195
+ items: {
196
+ type: "object",
197
+ properties: {
198
+ path: { type: "string", description: 'Relative file path (e.g. "server.js", "package.json", "src/utils.js")' },
199
+ content: { type: "string", description: "File content as a string. Use for small files." },
200
+ content_base64: { type: "string", description: "File content as base64-encoded string. Use when content has complex escaping." },
201
+ url: { type: "string", description: "URL to fetch file content from (e.g. raw GitHub URL). Server fetches it — no large payload needed." },
202
+ },
203
+ required: ["path"],
204
+ },
205
+ description: "Array of files to upload. Each file needs 'path' plus ONE of: 'content' (inline string), 'content_base64' (base64), or 'url' (server fetches it). Send one file per call for large files.",
206
+ },
207
+ },
208
+ required: ["connector_id", "files"],
209
+ },
210
+ },
182
211
  {
183
212
  name: "ateam_list_solutions",
184
213
  description: "List all solutions deployed in the Skill Builder.",
@@ -279,6 +308,186 @@ export const tools = [
279
308
  required: ["solution_id", "message"],
280
309
  },
281
310
  },
311
+
312
+ // ─── Developer Tools ────────────────────────────────────────────
313
+
314
+ {
315
+ name: "ateam_get_execution_logs",
316
+ description:
317
+ "Get execution logs for a solution — recent jobs with step traces, tool calls, errors, and timing. Essential for debugging what actually happened during skill execution.",
318
+ inputSchema: {
319
+ type: "object",
320
+ properties: {
321
+ solution_id: {
322
+ type: "string",
323
+ description: "The solution ID",
324
+ },
325
+ skill_id: {
326
+ type: "string",
327
+ description: "Optional: filter logs to a specific skill",
328
+ },
329
+ job_id: {
330
+ type: "string",
331
+ description: "Optional: get detailed trace for a specific job ID",
332
+ },
333
+ limit: {
334
+ type: "number",
335
+ description: "Max jobs to return (default: 10, max: 50)",
336
+ },
337
+ },
338
+ required: ["solution_id"],
339
+ },
340
+ },
341
+ {
342
+ name: "ateam_test_skill",
343
+ description:
344
+ "Send a test message to a deployed skill and get the full execution result. By default waits for completion (up to 60s). Set wait=false for async mode — returns job_id immediately, then poll with ateam_test_status.",
345
+ inputSchema: {
346
+ type: "object",
347
+ properties: {
348
+ solution_id: {
349
+ type: "string",
350
+ description: "The solution ID",
351
+ },
352
+ skill_id: {
353
+ type: "string",
354
+ description: "The skill ID to test (original or internal ID)",
355
+ },
356
+ message: {
357
+ type: "string",
358
+ description: "The test message to send to the skill",
359
+ },
360
+ wait: {
361
+ type: "boolean",
362
+ description:
363
+ "If true (default), wait for completion. If false, return job_id immediately for polling via ateam_test_status.",
364
+ },
365
+ },
366
+ required: ["solution_id", "skill_id", "message"],
367
+ },
368
+ },
369
+ {
370
+ name: "ateam_test_status",
371
+ description:
372
+ "Poll the progress of an async skill test. Returns iteration count, tool call steps, status, pending questions, and result when done. Uses the same data pipeline as the Job Progress UI.",
373
+ inputSchema: {
374
+ type: "object",
375
+ properties: {
376
+ solution_id: {
377
+ type: "string",
378
+ description: "The solution ID",
379
+ },
380
+ skill_id: {
381
+ type: "string",
382
+ description: "The skill ID",
383
+ },
384
+ job_id: {
385
+ type: "string",
386
+ description: "The job ID returned by ateam_test_skill",
387
+ },
388
+ },
389
+ required: ["solution_id", "skill_id", "job_id"],
390
+ },
391
+ },
392
+ {
393
+ name: "ateam_test_abort",
394
+ description:
395
+ "Abort a running skill test. Stops the job execution at the next iteration boundary.",
396
+ inputSchema: {
397
+ type: "object",
398
+ properties: {
399
+ solution_id: {
400
+ type: "string",
401
+ description: "The solution ID",
402
+ },
403
+ skill_id: {
404
+ type: "string",
405
+ description: "The skill ID",
406
+ },
407
+ job_id: {
408
+ type: "string",
409
+ description: "The job ID to abort",
410
+ },
411
+ },
412
+ required: ["solution_id", "skill_id", "job_id"],
413
+ },
414
+ },
415
+ {
416
+ name: "ateam_get_connector_source",
417
+ description:
418
+ "Read the source code of a connector's MCP server. Returns the files that make up the connector implementation.",
419
+ inputSchema: {
420
+ type: "object",
421
+ properties: {
422
+ solution_id: {
423
+ type: "string",
424
+ description: "The solution ID",
425
+ },
426
+ connector_id: {
427
+ type: "string",
428
+ description: "The connector ID",
429
+ },
430
+ },
431
+ required: ["solution_id", "connector_id"],
432
+ },
433
+ },
434
+ {
435
+ name: "ateam_get_metrics",
436
+ description:
437
+ "Get execution metrics — timing, tool stats, bottlenecks, signals, and recommendations. Use job_id for single-job deep analysis, or skill_id for recent history overview.",
438
+ inputSchema: {
439
+ type: "object",
440
+ properties: {
441
+ solution_id: {
442
+ type: "string",
443
+ description: "The solution ID",
444
+ },
445
+ job_id: {
446
+ type: "string",
447
+ description: "Optional: deep analysis for a specific job",
448
+ },
449
+ skill_id: {
450
+ type: "string",
451
+ description: "Optional: recent metrics for a specific skill",
452
+ },
453
+ },
454
+ required: ["solution_id"],
455
+ },
456
+ },
457
+ {
458
+ name: "ateam_diff",
459
+ description:
460
+ "Compare the current Builder definition against what's deployed in ADAS Core. Shows which skills are undeployed, orphaned, or have changed fields. Use skill_id to diff a single skill.",
461
+ inputSchema: {
462
+ type: "object",
463
+ properties: {
464
+ solution_id: {
465
+ type: "string",
466
+ description: "The solution ID",
467
+ },
468
+ skill_id: {
469
+ type: "string",
470
+ description: "Optional: diff a single skill instead of the whole solution",
471
+ },
472
+ },
473
+ required: ["solution_id"],
474
+ },
475
+ },
476
+ {
477
+ name: "ateam_delete_solution",
478
+ description:
479
+ "Delete a deployed solution and all its skills from A-Team. Use with caution — this removes the solution from both the Skill Builder and A-Team Core. Useful for cleaning up test solutions or starting fresh.",
480
+ inputSchema: {
481
+ type: "object",
482
+ properties: {
483
+ solution_id: {
484
+ type: "string",
485
+ description: "The solution ID to delete",
486
+ },
487
+ },
488
+ required: ["solution_id"],
489
+ },
490
+ },
282
491
  ];
283
492
 
284
493
  // ─── Tool handlers ──────────────────────────────────────────────────
@@ -303,9 +512,19 @@ const WRITE_TOOLS = new Set([
303
512
  "ateam_deploy_solution",
304
513
  "ateam_deploy_skill",
305
514
  "ateam_deploy_connector",
515
+ "ateam_upload_connector_files",
306
516
  "ateam_update",
307
517
  "ateam_redeploy",
308
518
  "ateam_solution_chat",
519
+ // Developer tools (read tenant-specific runtime data)
520
+ "ateam_get_execution_logs",
521
+ "ateam_test_skill",
522
+ "ateam_test_status",
523
+ "ateam_test_abort",
524
+ "ateam_get_connector_source",
525
+ "ateam_get_metrics",
526
+ "ateam_diff",
527
+ "ateam_delete_solution",
309
528
  ]);
310
529
 
311
530
  const handlers = {
@@ -334,8 +553,9 @@ const handlers = {
334
553
  { step: 1, title: "Clarify the goal", description: "Understand what the user wants their Team to do", suggested_tools: [] },
335
554
  { step: 2, title: "Generate Team map", description: "Design skills, solution architecture, and connectors", suggested_tools: ["ateam_get_spec", "ateam_get_examples", "ateam_get_workflows"] },
336
555
  { step: 3, title: "Validate", description: "Run validation before deploying", suggested_tools: ["ateam_validate_skill", "ateam_validate_solution"] },
337
- { step: 4, title: "Deploy", description: "Push the Team to A-Team Core", suggested_tools: ["ateam_auth", "ateam_deploy_solution"] },
556
+ { step: 4, title: "Deploy", description: "Push the Team to A-Team Core. If connector source code is too large for mcp_store, use ateam_upload_connector_files first (one file per call), then deploy without mcp_store.", suggested_tools: ["ateam_auth", "ateam_upload_connector_files", "ateam_deploy_solution"] },
338
557
  { step: 5, title: "Iterate", description: "Inspect, update, and redeploy as needed", suggested_tools: ["ateam_get_solution", "ateam_update", "ateam_redeploy", "ateam_solution_chat"] },
558
+ { step: 6, title: "Operate & Debug", description: "Test skills (async or sync), poll progress, abort tests, read execution logs, analyze metrics, diff definitions, inspect connector source", suggested_tools: ["ateam_test_skill", "ateam_test_status", "ateam_test_abort", "ateam_get_execution_logs", "ateam_get_metrics", "ateam_diff", "ateam_get_connector_source"] },
339
559
  ],
340
560
  first_questions: [
341
561
  { id: "goal", question: "What do you want your Team to accomplish?", type: "text" },
@@ -349,6 +569,18 @@ const handlers = {
349
569
  security: "https://ateam-ai.com/#security",
350
570
  engine: "https://ateam-ai.com/#engine",
351
571
  },
572
+ critical_connector_rules: {
573
+ _note: "CRITICAL: Read this before writing ANY connector code. Violations are caught at deploy time and BLOCKED.",
574
+ transport: "A-Team connectors use STDIO transport — child processes communicating via stdin/stdout JSON-RPC.",
575
+ MUST_use: "StdioServerTransport from @modelcontextprotocol/sdk, or raw readline over process.stdin.",
576
+ MUST_NOT_use: [
577
+ "express(), fastify(), Koa, or any web framework",
578
+ "http.createServer() or app.listen(PORT)",
579
+ "HttpServerTransport, SSEServerTransport, or StreamableHTTPServerTransport",
580
+ ],
581
+ stdout_rule: "stdout = JSON-RPC channel. Use console.error() for logging, NOT console.log().",
582
+ lifecycle_rule: "MCP servers must stay alive. Never call process.exit().",
583
+ },
352
584
  assistant_behavior_contract: {
353
585
  first_run_requirements: [
354
586
  "Explain platform before endpoints",
@@ -362,11 +594,14 @@ const handlers = {
362
594
  always: [
363
595
  "Explain Skill vs Solution vs Connector before deploying anything",
364
596
  "Validate before deploy",
597
+ "Study the connector example (ateam_get_examples type='connector') before writing connector code",
365
598
  "Ask discovery questions if goal unclear",
366
599
  ],
367
600
  never: [
368
601
  "Deploy before validation",
369
602
  "Dump raw spec unless requested",
603
+ "Write connector code that starts a web server (express, http.createServer, app.listen) — connectors MUST use stdio transport",
604
+ "Use HttpServerTransport, SSEServerTransport, or any non-stdio MCP transport",
370
605
  ],
371
606
  },
372
607
  }),
@@ -416,6 +651,28 @@ const handlers = {
416
651
  ateam_deploy_connector: async ({ connector }, sid) =>
417
652
  post("/deploy/connector", { connector }, sid),
418
653
 
654
+ ateam_upload_connector_files: async ({ connector_id, files }, sid) => {
655
+ // Resolve content_base64 and url into plain content before sending to backend
656
+ const resolved = [];
657
+ for (const file of files) {
658
+ if (!file.path) continue;
659
+ let content = file.content;
660
+ if (!content && file.content_base64) {
661
+ content = Buffer.from(file.content_base64, "base64").toString("utf-8");
662
+ }
663
+ if (!content && file.url) {
664
+ const resp = await fetch(file.url);
665
+ if (!resp.ok) throw new Error(`Failed to fetch ${file.url}: ${resp.status}`);
666
+ content = await resp.text();
667
+ }
668
+ if (content === undefined || content === null) {
669
+ throw new Error(`File "${file.path}": provide one of content, content_base64, or url`);
670
+ }
671
+ resolved.push({ path: file.path, content });
672
+ }
673
+ return post(`/deploy/mcp-store/${connector_id}`, { files: resolved }, sid);
674
+ },
675
+
419
676
  ateam_list_solutions: async (_args, sid) => get("/deploy/solutions", sid),
420
677
 
421
678
  ateam_get_solution: async ({ solution_id, view, skill_id }, sid) => {
@@ -449,6 +706,49 @@ const handlers = {
449
706
 
450
707
  ateam_solution_chat: async ({ solution_id, message }, sid) =>
451
708
  post(`/deploy/solutions/${solution_id}/chat`, { message }, sid),
709
+
710
+ // ─── Developer Tools ────────────────────────────────────────────
711
+
712
+ ateam_get_execution_logs: async ({ solution_id, skill_id, job_id, limit }, sid) => {
713
+ const qs = new URLSearchParams();
714
+ if (skill_id) qs.set("skill_id", skill_id);
715
+ if (job_id) qs.set("job_id", job_id);
716
+ if (limit) qs.set("limit", String(limit));
717
+ const qsStr = qs.toString() ? `?${qs}` : "";
718
+ return get(`/deploy/solutions/${solution_id}/logs${qsStr}`, sid);
719
+ },
720
+
721
+ ateam_test_skill: async ({ solution_id, skill_id, message, wait }, sid) => {
722
+ const asyncMode = wait === false;
723
+ const body = { message, ...(asyncMode ? { async: true } : {}) };
724
+ const timeoutMs = asyncMode ? 15_000 : 90_000;
725
+ return post(`/deploy/solutions/${solution_id}/skills/${skill_id}/test`, body, sid, { timeoutMs });
726
+ },
727
+
728
+ ateam_test_status: async ({ solution_id, skill_id, job_id }, sid) =>
729
+ get(`/deploy/solutions/${solution_id}/skills/${skill_id}/test/${job_id}`, sid),
730
+
731
+ ateam_test_abort: async ({ solution_id, skill_id, job_id }, sid) =>
732
+ del(`/deploy/solutions/${solution_id}/skills/${skill_id}/test/${job_id}`, sid),
733
+
734
+ ateam_get_connector_source: async ({ solution_id, connector_id }, sid) =>
735
+ get(`/deploy/solutions/${solution_id}/connectors/${connector_id}/source`, sid),
736
+
737
+ ateam_get_metrics: async ({ solution_id, job_id, skill_id }, sid) => {
738
+ const qs = new URLSearchParams();
739
+ if (job_id) qs.set("job_id", job_id);
740
+ if (skill_id) qs.set("skill_id", skill_id);
741
+ const qsStr = qs.toString() ? `?${qs}` : "";
742
+ return get(`/deploy/solutions/${solution_id}/metrics${qsStr}`, sid);
743
+ },
744
+
745
+ ateam_diff: async ({ solution_id, skill_id }, sid) => {
746
+ const qs = skill_id ? `?skill_id=${encodeURIComponent(skill_id)}` : "";
747
+ return get(`/deploy/solutions/${solution_id}/diff${qs}`, sid);
748
+ },
749
+
750
+ ateam_delete_solution: async ({ solution_id }, sid) =>
751
+ del(`/deploy/solutions/${solution_id}`, sid),
452
752
  };
453
753
 
454
754
  // ─── Response formatting ────────────────────────────────────────────