@ateam-ai/mcp 0.1.13 → 0.2.1
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/api.js +11 -0
- package/src/server.js +5 -3
- package/src/tools.js +448 -124
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -107,6 +107,17 @@ export function isAuthenticated(sessionId) {
|
|
|
107
107
|
return apiKey.length > 0;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Check if a session has been explicitly authenticated via ateam_auth.
|
|
112
|
+
* This checks ONLY per-session credentials, ignoring env vars.
|
|
113
|
+
* Used to gate mutating operations — env vars alone are not sufficient
|
|
114
|
+
* to deploy, update, or delete solutions.
|
|
115
|
+
*/
|
|
116
|
+
export function isExplicitlyAuthenticated(sessionId) {
|
|
117
|
+
if (!sessionId) return false;
|
|
118
|
+
return sessions.has(sessionId);
|
|
119
|
+
}
|
|
120
|
+
|
|
110
121
|
/**
|
|
111
122
|
* Remove session credentials (on disconnect).
|
|
112
123
|
*/
|
package/src/server.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
CallToolRequestSchema,
|
|
11
11
|
ListToolsRequestSchema,
|
|
12
12
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
13
|
-
import { tools, handleToolCall } from "./tools.js";
|
|
13
|
+
import { tools, coreTools, handleToolCall } from "./tools.js";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* @param {string} sessionId — identifier for credential isolation.
|
|
@@ -18,7 +18,7 @@ import { tools, handleToolCall } from "./tools.js";
|
|
|
18
18
|
*/
|
|
19
19
|
export function createServer(sessionId = "stdio") {
|
|
20
20
|
const server = new Server(
|
|
21
|
-
{ name: "ateam-mcp", version: "0.
|
|
21
|
+
{ name: "ateam-mcp", version: "0.3.0" },
|
|
22
22
|
{
|
|
23
23
|
capabilities: { tools: {} },
|
|
24
24
|
instructions: [
|
|
@@ -30,7 +30,9 @@ export function createServer(sessionId = "stdio") {
|
|
|
30
30
|
}
|
|
31
31
|
);
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
// Only advertise core tools — advanced tools are still callable but not listed.
|
|
34
|
+
// This reduces cognitive load from 23+ tools to ~11 in the tool surface.
|
|
35
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: coreTools }));
|
|
34
36
|
|
|
35
37
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
36
38
|
const { name, arguments: args } = request.params;
|
package/src/tools.js
CHANGED
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A-Team MCP tool definitions and handlers.
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Tools are split into two tiers:
|
|
5
|
+
* - Core tools (core: true) — shown in tools/list, the simplified developer loop
|
|
6
|
+
* - Advanced tools (core: false) — hidden from tools/list, still callable by name
|
|
7
|
+
*
|
|
8
|
+
* Core loop: bootstrap → auth → get_spec/examples → build_and_run → test → patch → test → done
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
11
|
import {
|
|
7
12
|
get, post, patch, del,
|
|
8
|
-
setSessionCredentials, isAuthenticated,
|
|
13
|
+
setSessionCredentials, isAuthenticated, isExplicitlyAuthenticated,
|
|
14
|
+
getCredentials, parseApiKey,
|
|
9
15
|
} from "./api.js";
|
|
10
16
|
|
|
11
17
|
// ─── Tool definitions ───────────────────────────────────────────────
|
|
12
18
|
|
|
13
19
|
export const tools = [
|
|
20
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
21
|
+
// CORE TOOLS — the simplified developer loop
|
|
22
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
23
|
+
|
|
14
24
|
{
|
|
15
25
|
name: "ateam_bootstrap",
|
|
26
|
+
core: true,
|
|
16
27
|
description:
|
|
17
28
|
"REQUIRED onboarding entrypoint for A-Team MCP. MUST be called when user greets, says hi, asks what this is, asks for help, explores capabilities, or when MCP is first connected. Returns platform explanation, example solutions, and assistant behavior instructions. Do NOT improvise an introduction — call this tool instead.",
|
|
18
29
|
inputSchema: {
|
|
@@ -22,8 +33,9 @@ export const tools = [
|
|
|
22
33
|
},
|
|
23
34
|
{
|
|
24
35
|
name: "ateam_auth",
|
|
36
|
+
core: true,
|
|
25
37
|
description:
|
|
26
|
-
"Authenticate with A-Team. Required before
|
|
38
|
+
"Authenticate with A-Team. Required before any tenant-aware operation (reading solutions, deploying, testing, etc.). The user can get their API key at https://mcp.ateam-ai.com/get-api-key. Only global endpoints (spec, examples, validate) work without auth. IMPORTANT: Even if environment variables (ADAS_API_KEY) are configured, you MUST call ateam_auth explicitly — env vars alone are not sufficient.",
|
|
27
39
|
inputSchema: {
|
|
28
40
|
type: "object",
|
|
29
41
|
properties: {
|
|
@@ -41,6 +53,7 @@ export const tools = [
|
|
|
41
53
|
},
|
|
42
54
|
{
|
|
43
55
|
name: "ateam_get_spec",
|
|
56
|
+
core: true,
|
|
44
57
|
description:
|
|
45
58
|
"Get the A-Team specification — schemas, validation rules, system tools, agent guides, and templates. Start here after bootstrap to understand how to build skills and solutions.",
|
|
46
59
|
inputSchema: {
|
|
@@ -58,6 +71,7 @@ export const tools = [
|
|
|
58
71
|
},
|
|
59
72
|
{
|
|
60
73
|
name: "ateam_get_workflows",
|
|
74
|
+
core: true,
|
|
61
75
|
description:
|
|
62
76
|
"Get the builder workflows — step-by-step state machines for building skills and solutions. Use this to guide users through the entire build process conversationally. Returns phases, what to ask, what to build, exit criteria, and tips for each stage.",
|
|
63
77
|
inputSchema: {
|
|
@@ -67,6 +81,7 @@ export const tools = [
|
|
|
67
81
|
},
|
|
68
82
|
{
|
|
69
83
|
name: "ateam_get_examples",
|
|
84
|
+
core: true,
|
|
70
85
|
description:
|
|
71
86
|
"Get complete working examples that pass validation. Study these before building your own.",
|
|
72
87
|
inputSchema: {
|
|
@@ -82,10 +97,169 @@ export const tools = [
|
|
|
82
97
|
required: ["type"],
|
|
83
98
|
},
|
|
84
99
|
},
|
|
100
|
+
{
|
|
101
|
+
name: "ateam_build_and_run",
|
|
102
|
+
core: true,
|
|
103
|
+
description:
|
|
104
|
+
"Build and deploy a governed AI Team solution in one step. Validates, deploys, health-checks, and optionally runs a warm test — all in one call. Use this instead of calling validate, deploy, and health separately. Requires authentication.",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
solution: {
|
|
109
|
+
type: "object",
|
|
110
|
+
description: "Solution architecture — identity, grants, handoffs, routing",
|
|
111
|
+
},
|
|
112
|
+
skills: {
|
|
113
|
+
type: "array",
|
|
114
|
+
items: { type: "object" },
|
|
115
|
+
description: "Array of full skill definitions",
|
|
116
|
+
},
|
|
117
|
+
connectors: {
|
|
118
|
+
type: "array",
|
|
119
|
+
items: { type: "object" },
|
|
120
|
+
description: "Optional: connector metadata (id, name, transport). Entry points auto-detected from mcp_store.",
|
|
121
|
+
},
|
|
122
|
+
mcp_store: {
|
|
123
|
+
type: "object",
|
|
124
|
+
description: "Optional: connector source code files. Key = connector id, value = array of {path, content}.",
|
|
125
|
+
},
|
|
126
|
+
test_message: {
|
|
127
|
+
type: "string",
|
|
128
|
+
description: "Optional: send a test message after deployment to verify the skill works. Returns the full execution result.",
|
|
129
|
+
},
|
|
130
|
+
test_skill_id: {
|
|
131
|
+
type: "string",
|
|
132
|
+
description: "Optional: which skill to test (defaults to the first skill).",
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
required: ["solution", "skills"],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "ateam_test_skill",
|
|
140
|
+
core: true,
|
|
141
|
+
description:
|
|
142
|
+
"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.",
|
|
143
|
+
inputSchema: {
|
|
144
|
+
type: "object",
|
|
145
|
+
properties: {
|
|
146
|
+
solution_id: {
|
|
147
|
+
type: "string",
|
|
148
|
+
description: "The solution ID",
|
|
149
|
+
},
|
|
150
|
+
skill_id: {
|
|
151
|
+
type: "string",
|
|
152
|
+
description: "The skill ID to test (original or internal ID)",
|
|
153
|
+
},
|
|
154
|
+
message: {
|
|
155
|
+
type: "string",
|
|
156
|
+
description: "The test message to send to the skill",
|
|
157
|
+
},
|
|
158
|
+
wait: {
|
|
159
|
+
type: "boolean",
|
|
160
|
+
description:
|
|
161
|
+
"If true (default), wait for completion. If false, return job_id immediately for polling via ateam_test_status.",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
required: ["solution_id", "skill_id", "message"],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "ateam_patch",
|
|
169
|
+
core: true,
|
|
170
|
+
description:
|
|
171
|
+
"Update a deployed skill or solution, redeploy, and optionally re-test — all in one step. Use this instead of calling update + redeploy separately. Requires authentication.",
|
|
172
|
+
inputSchema: {
|
|
173
|
+
type: "object",
|
|
174
|
+
properties: {
|
|
175
|
+
solution_id: {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "The solution ID",
|
|
178
|
+
},
|
|
179
|
+
target: {
|
|
180
|
+
type: "string",
|
|
181
|
+
enum: ["solution", "skill"],
|
|
182
|
+
description: "What to update: 'solution' or 'skill'",
|
|
183
|
+
},
|
|
184
|
+
skill_id: {
|
|
185
|
+
type: "string",
|
|
186
|
+
description: "Required when target is 'skill'",
|
|
187
|
+
},
|
|
188
|
+
updates: {
|
|
189
|
+
type: "object",
|
|
190
|
+
description:
|
|
191
|
+
"The update payload — use dot notation for scalars (e.g. 'problem.statement'), and tools_push/tools_delete/tools_update for array operations",
|
|
192
|
+
},
|
|
193
|
+
test_message: {
|
|
194
|
+
type: "string",
|
|
195
|
+
description: "Optional: re-test the skill after patching. Requires skill_id.",
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
required: ["solution_id", "target", "updates"],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: "ateam_get_solution",
|
|
203
|
+
core: true,
|
|
204
|
+
description:
|
|
205
|
+
"Read solution state — definition, skills, health, status, or export. Use this to inspect deployed solutions.",
|
|
206
|
+
inputSchema: {
|
|
207
|
+
type: "object",
|
|
208
|
+
properties: {
|
|
209
|
+
solution_id: {
|
|
210
|
+
type: "string",
|
|
211
|
+
description: "The solution ID",
|
|
212
|
+
},
|
|
213
|
+
view: {
|
|
214
|
+
type: "string",
|
|
215
|
+
enum: ["definition", "skills", "health", "status", "export", "validate", "connectors_health"],
|
|
216
|
+
description:
|
|
217
|
+
"What to read: 'definition' = full solution def, 'skills' = list skills, 'health' = live health check, 'status' = deploy status, 'export' = exportable bundle, 'validate' = re-validate from stored state, 'connectors_health' = connector status",
|
|
218
|
+
},
|
|
219
|
+
skill_id: {
|
|
220
|
+
type: "string",
|
|
221
|
+
description: "Optional: read a specific skill by ID (original or internal)",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
required: ["solution_id", "view"],
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "ateam_list_solutions",
|
|
229
|
+
core: true,
|
|
230
|
+
description: "List all solutions deployed in the Skill Builder.",
|
|
231
|
+
inputSchema: {
|
|
232
|
+
type: "object",
|
|
233
|
+
properties: {},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: "ateam_delete_solution",
|
|
238
|
+
core: true,
|
|
239
|
+
description:
|
|
240
|
+
"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.",
|
|
241
|
+
inputSchema: {
|
|
242
|
+
type: "object",
|
|
243
|
+
properties: {
|
|
244
|
+
solution_id: {
|
|
245
|
+
type: "string",
|
|
246
|
+
description: "The solution ID to delete",
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
required: ["solution_id"],
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
254
|
+
// ADVANCED TOOLS — hidden from tools/list, still callable by name
|
|
255
|
+
// Use these for manual lifecycle control, debugging, and diagnostics
|
|
256
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
257
|
+
|
|
85
258
|
{
|
|
86
259
|
name: "ateam_validate_skill",
|
|
260
|
+
core: false,
|
|
87
261
|
description:
|
|
88
|
-
"Validate a skill definition through the 5-stage A-Team validation pipeline.
|
|
262
|
+
"Validate a skill definition through the 5-stage A-Team validation pipeline. Returns errors and suggestions to fix. (Advanced — ateam_build_and_run validates automatically.)",
|
|
89
263
|
inputSchema: {
|
|
90
264
|
type: "object",
|
|
91
265
|
properties: {
|
|
@@ -99,8 +273,9 @@ export const tools = [
|
|
|
99
273
|
},
|
|
100
274
|
{
|
|
101
275
|
name: "ateam_validate_solution",
|
|
276
|
+
core: false,
|
|
102
277
|
description:
|
|
103
|
-
"Validate a governed AI Team solution — cross-skill contracts, grant economy, handoffs, and LLM quality scoring.
|
|
278
|
+
"Validate a governed AI Team solution — cross-skill contracts, grant economy, handoffs, and LLM quality scoring. (Advanced — ateam_build_and_run validates automatically.)",
|
|
104
279
|
inputSchema: {
|
|
105
280
|
type: "object",
|
|
106
281
|
properties: {
|
|
@@ -119,8 +294,9 @@ export const tools = [
|
|
|
119
294
|
},
|
|
120
295
|
{
|
|
121
296
|
name: "ateam_deploy_solution",
|
|
297
|
+
core: false,
|
|
122
298
|
description:
|
|
123
|
-
"Deploy a governed AI Team solution to A-Team Core
|
|
299
|
+
"Deploy a governed AI Team solution to A-Team Core. (Advanced — prefer ateam_build_and_run which validates + deploys + health-checks in one step.)",
|
|
124
300
|
inputSchema: {
|
|
125
301
|
type: "object",
|
|
126
302
|
properties: {
|
|
@@ -136,12 +312,12 @@ export const tools = [
|
|
|
136
312
|
connectors: {
|
|
137
313
|
type: "array",
|
|
138
314
|
items: { type: "object" },
|
|
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
|
|
315
|
+
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.",
|
|
140
316
|
},
|
|
141
317
|
mcp_store: {
|
|
142
318
|
type: "object",
|
|
143
319
|
description:
|
|
144
|
-
"Optional: connector source code files. Key = connector id, value = array of {path, content}.
|
|
320
|
+
"Optional: connector source code files. Key = connector id, value = array of {path, content}.",
|
|
145
321
|
},
|
|
146
322
|
},
|
|
147
323
|
required: ["solution", "skills"],
|
|
@@ -149,7 +325,8 @@ export const tools = [
|
|
|
149
325
|
},
|
|
150
326
|
{
|
|
151
327
|
name: "ateam_deploy_skill",
|
|
152
|
-
|
|
328
|
+
core: false,
|
|
329
|
+
description: "Deploy a single skill into an existing solution. (Advanced — use ateam_build_and_run for new solutions.)",
|
|
153
330
|
inputSchema: {
|
|
154
331
|
type: "object",
|
|
155
332
|
properties: {
|
|
@@ -167,7 +344,8 @@ export const tools = [
|
|
|
167
344
|
},
|
|
168
345
|
{
|
|
169
346
|
name: "ateam_deploy_connector",
|
|
170
|
-
|
|
347
|
+
core: false,
|
|
348
|
+
description: "Deploy a connector — registers in the Skill Builder catalog and connects in A-Team Core. (Advanced.)",
|
|
171
349
|
inputSchema: {
|
|
172
350
|
type: "object",
|
|
173
351
|
properties: {
|
|
@@ -181,8 +359,9 @@ export const tools = [
|
|
|
181
359
|
},
|
|
182
360
|
{
|
|
183
361
|
name: "ateam_upload_connector_files",
|
|
362
|
+
core: false,
|
|
184
363
|
description:
|
|
185
|
-
"Upload source files for a connector's MCP server. Use this INSTEAD of mcp_store in
|
|
364
|
+
"Upload source files for a connector's MCP server. Use this INSTEAD of mcp_store in ateam_build_and_run when the source code is too large to inline. Upload files first, then build_and_run without mcp_store. (Advanced.)",
|
|
186
365
|
inputSchema: {
|
|
187
366
|
type: "object",
|
|
188
367
|
properties: {
|
|
@@ -202,49 +381,17 @@ export const tools = [
|
|
|
202
381
|
},
|
|
203
382
|
required: ["path"],
|
|
204
383
|
},
|
|
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).
|
|
384
|
+
description: "Array of files to upload. Each file needs 'path' plus ONE of: 'content' (inline string), 'content_base64' (base64), or 'url' (server fetches it).",
|
|
206
385
|
},
|
|
207
386
|
},
|
|
208
387
|
required: ["connector_id", "files"],
|
|
209
388
|
},
|
|
210
389
|
},
|
|
211
|
-
{
|
|
212
|
-
name: "ateam_list_solutions",
|
|
213
|
-
description: "List all solutions deployed in the Skill Builder.",
|
|
214
|
-
inputSchema: {
|
|
215
|
-
type: "object",
|
|
216
|
-
properties: {},
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
name: "ateam_get_solution",
|
|
221
|
-
description:
|
|
222
|
-
"Read solution state — definition, skills, health, status, or export. Use this to inspect deployed solutions.",
|
|
223
|
-
inputSchema: {
|
|
224
|
-
type: "object",
|
|
225
|
-
properties: {
|
|
226
|
-
solution_id: {
|
|
227
|
-
type: "string",
|
|
228
|
-
description: "The solution ID",
|
|
229
|
-
},
|
|
230
|
-
view: {
|
|
231
|
-
type: "string",
|
|
232
|
-
enum: ["definition", "skills", "health", "status", "export", "validate", "connectors_health"],
|
|
233
|
-
description:
|
|
234
|
-
"What to read: 'definition' = full solution def, 'skills' = list skills, 'health' = live health check, 'status' = deploy status, 'export' = exportable bundle, 'validate' = re-validate from stored state, 'connectors_health' = connector status",
|
|
235
|
-
},
|
|
236
|
-
skill_id: {
|
|
237
|
-
type: "string",
|
|
238
|
-
description: "Optional: read a specific skill by ID (original or internal)",
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
required: ["solution_id", "view"],
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
390
|
{
|
|
245
391
|
name: "ateam_update",
|
|
392
|
+
core: false,
|
|
246
393
|
description:
|
|
247
|
-
"Update a deployed solution or skill incrementally using PATCH.
|
|
394
|
+
"Update a deployed solution or skill incrementally using PATCH. (Advanced — prefer ateam_patch which updates + redeploys + tests in one step.)",
|
|
248
395
|
inputSchema: {
|
|
249
396
|
type: "object",
|
|
250
397
|
properties: {
|
|
@@ -272,8 +419,9 @@ export const tools = [
|
|
|
272
419
|
},
|
|
273
420
|
{
|
|
274
421
|
name: "ateam_redeploy",
|
|
422
|
+
core: false,
|
|
275
423
|
description:
|
|
276
|
-
"Re-deploy after making updates.
|
|
424
|
+
"Re-deploy after making updates. (Advanced — prefer ateam_patch which updates + redeploys in one step.)",
|
|
277
425
|
inputSchema: {
|
|
278
426
|
type: "object",
|
|
279
427
|
properties: {
|
|
@@ -291,8 +439,9 @@ export const tools = [
|
|
|
291
439
|
},
|
|
292
440
|
{
|
|
293
441
|
name: "ateam_solution_chat",
|
|
442
|
+
core: false,
|
|
294
443
|
description:
|
|
295
|
-
"Send a message to the Solution Bot — an AI assistant that understands your deployed solution and can help with modifications.",
|
|
444
|
+
"Send a message to the Solution Bot — an AI assistant that understands your deployed solution and can help with modifications. (Advanced.)",
|
|
296
445
|
inputSchema: {
|
|
297
446
|
type: "object",
|
|
298
447
|
properties: {
|
|
@@ -308,13 +457,11 @@ export const tools = [
|
|
|
308
457
|
required: ["solution_id", "message"],
|
|
309
458
|
},
|
|
310
459
|
},
|
|
311
|
-
|
|
312
|
-
// ─── Developer Tools ────────────────────────────────────────────
|
|
313
|
-
|
|
314
460
|
{
|
|
315
461
|
name: "ateam_get_execution_logs",
|
|
462
|
+
core: false,
|
|
316
463
|
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.",
|
|
464
|
+
"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. (Advanced.)",
|
|
318
465
|
inputSchema: {
|
|
319
466
|
type: "object",
|
|
320
467
|
properties: {
|
|
@@ -338,38 +485,11 @@ export const tools = [
|
|
|
338
485
|
required: ["solution_id"],
|
|
339
486
|
},
|
|
340
487
|
},
|
|
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
488
|
{
|
|
370
489
|
name: "ateam_test_status",
|
|
490
|
+
core: false,
|
|
371
491
|
description:
|
|
372
|
-
"Poll the progress of an async skill test. Returns iteration count, tool call steps, status, pending questions, and result when done.
|
|
492
|
+
"Poll the progress of an async skill test. Returns iteration count, tool call steps, status, pending questions, and result when done. (Advanced — use ateam_test_skill with wait=true for synchronous testing.)",
|
|
373
493
|
inputSchema: {
|
|
374
494
|
type: "object",
|
|
375
495
|
properties: {
|
|
@@ -391,8 +511,9 @@ export const tools = [
|
|
|
391
511
|
},
|
|
392
512
|
{
|
|
393
513
|
name: "ateam_test_abort",
|
|
514
|
+
core: false,
|
|
394
515
|
description:
|
|
395
|
-
"Abort a running skill test. Stops the job execution at the next iteration boundary.",
|
|
516
|
+
"Abort a running skill test. Stops the job execution at the next iteration boundary. (Advanced.)",
|
|
396
517
|
inputSchema: {
|
|
397
518
|
type: "object",
|
|
398
519
|
properties: {
|
|
@@ -414,8 +535,9 @@ export const tools = [
|
|
|
414
535
|
},
|
|
415
536
|
{
|
|
416
537
|
name: "ateam_get_connector_source",
|
|
538
|
+
core: false,
|
|
417
539
|
description:
|
|
418
|
-
"Read the source code of a connector's MCP server. Returns the files that make up the connector implementation.",
|
|
540
|
+
"Read the source code of a connector's MCP server. Returns the files that make up the connector implementation. (Advanced.)",
|
|
419
541
|
inputSchema: {
|
|
420
542
|
type: "object",
|
|
421
543
|
properties: {
|
|
@@ -433,8 +555,9 @@ export const tools = [
|
|
|
433
555
|
},
|
|
434
556
|
{
|
|
435
557
|
name: "ateam_get_metrics",
|
|
558
|
+
core: false,
|
|
436
559
|
description:
|
|
437
|
-
"Get execution metrics — timing, tool stats, bottlenecks, signals, and recommendations.
|
|
560
|
+
"Get execution metrics — timing, tool stats, bottlenecks, signals, and recommendations. (Advanced.)",
|
|
438
561
|
inputSchema: {
|
|
439
562
|
type: "object",
|
|
440
563
|
properties: {
|
|
@@ -456,8 +579,9 @@ export const tools = [
|
|
|
456
579
|
},
|
|
457
580
|
{
|
|
458
581
|
name: "ateam_diff",
|
|
582
|
+
core: false,
|
|
459
583
|
description:
|
|
460
|
-
"Compare the current Builder definition against what's deployed in ADAS Core. Shows which skills are undeployed, orphaned, or have changed fields.
|
|
584
|
+
"Compare the current Builder definition against what's deployed in ADAS Core. Shows which skills are undeployed, orphaned, or have changed fields. (Advanced.)",
|
|
461
585
|
inputSchema: {
|
|
462
586
|
type: "object",
|
|
463
587
|
properties: {
|
|
@@ -473,23 +597,14 @@ export const tools = [
|
|
|
473
597
|
required: ["solution_id"],
|
|
474
598
|
},
|
|
475
599
|
},
|
|
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
|
-
},
|
|
491
600
|
];
|
|
492
601
|
|
|
602
|
+
/**
|
|
603
|
+
* Core tools — shown in MCP tools/list.
|
|
604
|
+
* Advanced tools are still callable but not advertised.
|
|
605
|
+
*/
|
|
606
|
+
export const coreTools = tools.filter(t => t.core !== false);
|
|
607
|
+
|
|
493
608
|
// ─── Tool handlers ──────────────────────────────────────────────────
|
|
494
609
|
|
|
495
610
|
const SPEC_PATHS = {
|
|
@@ -507,16 +622,25 @@ const EXAMPLE_PATHS = {
|
|
|
507
622
|
solution: "/spec/examples/solution",
|
|
508
623
|
};
|
|
509
624
|
|
|
510
|
-
// Tools that require
|
|
511
|
-
|
|
625
|
+
// Tools that are tenant-aware — require EXPLICIT ateam_auth (env vars alone not enough).
|
|
626
|
+
// This prevents accidental reads/writes to the wrong tenant when env vars are
|
|
627
|
+
// baked into MCP config (e.g., ADAS_TENANT + ADAS_API_KEY in ~/.claude.json).
|
|
628
|
+
// Any tool that touches tenant-specific data (solutions, skills, logs, tests) is here.
|
|
629
|
+
const TENANT_TOOLS = new Set([
|
|
630
|
+
// Write operations
|
|
631
|
+
"ateam_build_and_run",
|
|
632
|
+
"ateam_patch",
|
|
512
633
|
"ateam_deploy_solution",
|
|
513
634
|
"ateam_deploy_skill",
|
|
514
635
|
"ateam_deploy_connector",
|
|
515
636
|
"ateam_upload_connector_files",
|
|
516
637
|
"ateam_update",
|
|
517
638
|
"ateam_redeploy",
|
|
639
|
+
"ateam_delete_solution",
|
|
518
640
|
"ateam_solution_chat",
|
|
519
|
-
//
|
|
641
|
+
// Read operations (tenant-specific data)
|
|
642
|
+
"ateam_list_solutions",
|
|
643
|
+
"ateam_get_solution",
|
|
520
644
|
"ateam_get_execution_logs",
|
|
521
645
|
"ateam_test_skill",
|
|
522
646
|
"ateam_test_status",
|
|
@@ -524,9 +648,11 @@ const WRITE_TOOLS = new Set([
|
|
|
524
648
|
"ateam_get_connector_source",
|
|
525
649
|
"ateam_get_metrics",
|
|
526
650
|
"ateam_diff",
|
|
527
|
-
"ateam_delete_solution",
|
|
528
651
|
]);
|
|
529
652
|
|
|
653
|
+
/** Small delay helper */
|
|
654
|
+
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
|
|
655
|
+
|
|
530
656
|
const handlers = {
|
|
531
657
|
ateam_bootstrap: async () => ({
|
|
532
658
|
platform_positioning: {
|
|
@@ -549,20 +675,28 @@ const handlers = {
|
|
|
549
675
|
{ name: "Customer Support Operations Team", description: "Multi-role support system with escalation, refund controls, CRM integration" },
|
|
550
676
|
{ name: "Enterprise Compliance Platform", description: "Approval flows, audit logs, policy enforcement" },
|
|
551
677
|
],
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
678
|
+
developer_loop: {
|
|
679
|
+
_note: "This is the recommended build loop. Only 4 steps from definition to running skill.",
|
|
680
|
+
steps: [
|
|
681
|
+
{ step: 1, action: "Learn", description: "Get the spec and study examples", tools: ["ateam_get_spec", "ateam_get_examples"] },
|
|
682
|
+
{ step: 2, action: "Build & Run", description: "Define your solution + skills, then validate, deploy, and health-check in one call. Optionally include a test_message to verify it works immediately.", tools: ["ateam_build_and_run"] },
|
|
683
|
+
{ step: 3, action: "Test", description: "Send test messages to your deployed skill and see the full execution trace.", tools: ["ateam_test_skill"] },
|
|
684
|
+
{ step: 4, action: "Iterate", description: "Patch the skill (update + redeploy + re-test in one call), repeat until satisfied.", tools: ["ateam_patch"] },
|
|
685
|
+
],
|
|
686
|
+
},
|
|
560
687
|
first_questions: [
|
|
561
688
|
{ id: "goal", question: "What do you want your Team to accomplish?", type: "text" },
|
|
562
689
|
{ id: "domain", question: "Which domain fits best?", type: "enum", options: ["ecommerce", "logistics", "enterprise_ops", "other"] },
|
|
563
690
|
{ id: "systems", question: "Which systems should the Team connect to?", type: "multi_select", options: ["slack", "email", "zendesk", "shopify", "jira", "postgres", "custom_api", "none"] },
|
|
564
691
|
{ id: "security", question: "What environment constraints?", type: "enum", options: ["sandbox", "controlled", "regulated"] },
|
|
565
692
|
],
|
|
693
|
+
advanced_tools: {
|
|
694
|
+
_note: "These tools are available but hidden from the default tool list. Call them by name when you need fine-grained control.",
|
|
695
|
+
debugging: ["ateam_get_execution_logs", "ateam_get_metrics", "ateam_diff", "ateam_get_connector_source"],
|
|
696
|
+
manual_lifecycle: ["ateam_validate_skill", "ateam_validate_solution", "ateam_deploy_solution", "ateam_deploy_skill", "ateam_deploy_connector", "ateam_update", "ateam_redeploy"],
|
|
697
|
+
async_testing: ["ateam_test_status", "ateam_test_abort"],
|
|
698
|
+
other: ["ateam_upload_connector_files", "ateam_solution_chat"],
|
|
699
|
+
},
|
|
566
700
|
static_pages: {
|
|
567
701
|
features: "https://ateam-ai.com/#features",
|
|
568
702
|
use_cases: "https://ateam-ai.com/#usecases",
|
|
@@ -589,19 +723,20 @@ const handlers = {
|
|
|
589
723
|
"Define Skill vs Solution vs Connector",
|
|
590
724
|
"Ask user what solution they want to build",
|
|
591
725
|
],
|
|
592
|
-
thinking_order: ["Platform", "Solution", "Skills", "Connectors", "Governance", "
|
|
726
|
+
thinking_order: ["Platform", "Solution", "Skills", "Connectors", "Governance", "Build & Run"],
|
|
593
727
|
tone: "Architectural, enterprise-grade, serious",
|
|
594
728
|
always: [
|
|
595
|
-
"Explain Skill vs Solution vs Connector before
|
|
596
|
-
"
|
|
729
|
+
"Explain Skill vs Solution vs Connector before building",
|
|
730
|
+
"Use ateam_build_and_run for the full lifecycle (validates automatically)",
|
|
731
|
+
"Use ateam_patch for iterations (updates + redeploys automatically)",
|
|
597
732
|
"Study the connector example (ateam_get_examples type='connector') before writing connector code",
|
|
598
733
|
"Ask discovery questions if goal unclear",
|
|
599
734
|
],
|
|
600
735
|
never: [
|
|
601
|
-
"
|
|
736
|
+
"Call validate + deploy + health separately when ateam_build_and_run does it in one step",
|
|
737
|
+
"Call update + redeploy separately when ateam_patch does it in one step",
|
|
602
738
|
"Dump raw spec unless requested",
|
|
603
|
-
"Write connector code that starts a web server
|
|
604
|
-
"Use HttpServerTransport, SSEServerTransport, or any non-stdio MCP transport",
|
|
739
|
+
"Write connector code that starts a web server — connectors MUST use stdio transport",
|
|
605
740
|
],
|
|
606
741
|
},
|
|
607
742
|
}),
|
|
@@ -637,6 +772,188 @@ const handlers = {
|
|
|
637
772
|
|
|
638
773
|
ateam_get_examples: async ({ type }, sid) => get(EXAMPLE_PATHS[type], sid),
|
|
639
774
|
|
|
775
|
+
// ─── Composite: Build & Run ────────────────────────────────────────
|
|
776
|
+
// Validates → Deploys → Health-checks → Optionally tests
|
|
777
|
+
// One call replaces: validate_solution + deploy_solution + get_solution(health)
|
|
778
|
+
|
|
779
|
+
ateam_build_and_run: async ({ solution, skills, connectors, mcp_store, test_message, test_skill_id }, sid) => {
|
|
780
|
+
const phases = [];
|
|
781
|
+
|
|
782
|
+
// Phase 1: Validate
|
|
783
|
+
let validation;
|
|
784
|
+
try {
|
|
785
|
+
validation = await post("/validate/solution", { solution, skills }, sid);
|
|
786
|
+
phases.push({ phase: "validate", status: "done" });
|
|
787
|
+
} catch (err) {
|
|
788
|
+
return {
|
|
789
|
+
ok: false,
|
|
790
|
+
phase: "validation",
|
|
791
|
+
error: err.message,
|
|
792
|
+
message: "Validation call failed. Check your solution/skill format against the spec (ateam_get_spec topic='solution').",
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
// Check for blocking errors
|
|
797
|
+
const errors = validation.errors || validation.validation?.errors || [];
|
|
798
|
+
if (errors.length > 0) {
|
|
799
|
+
return {
|
|
800
|
+
ok: false,
|
|
801
|
+
phase: "validation",
|
|
802
|
+
errors,
|
|
803
|
+
warnings: validation.warnings || validation.validation?.warnings || [],
|
|
804
|
+
message: `Validation found ${errors.length} error(s). Fix them and try again.`,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Phase 2: Deploy
|
|
809
|
+
let deploy;
|
|
810
|
+
try {
|
|
811
|
+
deploy = await post("/deploy/solution", { solution, skills, connectors, mcp_store }, sid);
|
|
812
|
+
phases.push({ phase: "deploy", status: deploy.ok ? "done" : "failed" });
|
|
813
|
+
} catch (err) {
|
|
814
|
+
return {
|
|
815
|
+
ok: false,
|
|
816
|
+
phase: "deployment",
|
|
817
|
+
phases,
|
|
818
|
+
error: err.message,
|
|
819
|
+
validation_warnings: validation.warnings || [],
|
|
820
|
+
message: "Deployment failed. See error details above.",
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (!deploy.ok) {
|
|
825
|
+
return {
|
|
826
|
+
ok: false,
|
|
827
|
+
phase: "deployment",
|
|
828
|
+
phases,
|
|
829
|
+
deploy,
|
|
830
|
+
validation_warnings: validation.warnings || [],
|
|
831
|
+
message: "Deployment returned an error. See deploy details above.",
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Phase 3: Health check (with brief wait for propagation)
|
|
836
|
+
let health;
|
|
837
|
+
try {
|
|
838
|
+
await sleep(2000);
|
|
839
|
+
health = await get(`/deploy/solutions/${solution.id}/health`, sid);
|
|
840
|
+
phases.push({ phase: "health", status: "done" });
|
|
841
|
+
} catch (err) {
|
|
842
|
+
health = { error: err.message };
|
|
843
|
+
phases.push({ phase: "health", status: "error", error: err.message });
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// Phase 4: Warm test (optional)
|
|
847
|
+
let test_result;
|
|
848
|
+
if (test_message) {
|
|
849
|
+
const skillId = test_skill_id || skills?.[0]?.id;
|
|
850
|
+
if (skillId) {
|
|
851
|
+
try {
|
|
852
|
+
test_result = await post(
|
|
853
|
+
`/deploy/solutions/${solution.id}/skills/${skillId}/test`,
|
|
854
|
+
{ message: test_message },
|
|
855
|
+
sid,
|
|
856
|
+
{ timeoutMs: 90_000 },
|
|
857
|
+
);
|
|
858
|
+
phases.push({ phase: "test", status: "done", skill_id: skillId });
|
|
859
|
+
} catch (err) {
|
|
860
|
+
test_result = { error: err.message };
|
|
861
|
+
phases.push({ phase: "test", status: "error", error: err.message });
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
return {
|
|
867
|
+
ok: true,
|
|
868
|
+
solution_id: solution.id,
|
|
869
|
+
phases,
|
|
870
|
+
deploy: {
|
|
871
|
+
skills_deployed: deploy.import?.skills || [],
|
|
872
|
+
connectors: deploy.import?.connectors || 0,
|
|
873
|
+
...(deploy.deploy_warnings?.length > 0 && { warnings: deploy.deploy_warnings }),
|
|
874
|
+
...(deploy.auto_expanded_skills?.length > 0 && { auto_expanded: deploy.auto_expanded_skills }),
|
|
875
|
+
},
|
|
876
|
+
health,
|
|
877
|
+
...(test_result && { test_result }),
|
|
878
|
+
...(validation.warnings?.length > 0 && { validation_warnings: validation.warnings }),
|
|
879
|
+
};
|
|
880
|
+
},
|
|
881
|
+
|
|
882
|
+
// ─── Composite: Patch ──────────────────────────────────────────────
|
|
883
|
+
// Updates → Redeploys → Optionally tests
|
|
884
|
+
// One call replaces: ateam_update + ateam_redeploy
|
|
885
|
+
|
|
886
|
+
ateam_patch: async ({ solution_id, target, skill_id, updates, test_message }, sid) => {
|
|
887
|
+
const phases = [];
|
|
888
|
+
|
|
889
|
+
// Phase 1: Apply PATCH
|
|
890
|
+
let patchResult;
|
|
891
|
+
try {
|
|
892
|
+
if (target === "skill") {
|
|
893
|
+
patchResult = await patch(`/deploy/solutions/${solution_id}/skills/${skill_id}`, { updates }, sid);
|
|
894
|
+
} else {
|
|
895
|
+
patchResult = await patch(`/deploy/solutions/${solution_id}`, { state_update: updates }, sid);
|
|
896
|
+
}
|
|
897
|
+
phases.push({ phase: "update", status: "done" });
|
|
898
|
+
} catch (err) {
|
|
899
|
+
return {
|
|
900
|
+
ok: false,
|
|
901
|
+
phase: "update",
|
|
902
|
+
error: err.message,
|
|
903
|
+
message: "Patch failed. Check your updates payload format.",
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// Phase 2: Redeploy
|
|
908
|
+
let redeployResult;
|
|
909
|
+
try {
|
|
910
|
+
if (target === "skill" && skill_id) {
|
|
911
|
+
redeployResult = await post(`/deploy/solutions/${solution_id}/skills/${skill_id}/redeploy`, {}, sid);
|
|
912
|
+
} else {
|
|
913
|
+
redeployResult = await post(`/deploy/solutions/${solution_id}/redeploy`, {}, sid);
|
|
914
|
+
}
|
|
915
|
+
phases.push({ phase: "redeploy", status: "done" });
|
|
916
|
+
} catch (err) {
|
|
917
|
+
return {
|
|
918
|
+
ok: false,
|
|
919
|
+
phase: "redeploy",
|
|
920
|
+
phases,
|
|
921
|
+
patch: patchResult,
|
|
922
|
+
error: err.message,
|
|
923
|
+
message: "Update succeeded but redeploy failed. Try ateam_redeploy manually.",
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// Phase 3: Optional re-test
|
|
928
|
+
let test_result;
|
|
929
|
+
if (test_message && skill_id) {
|
|
930
|
+
try {
|
|
931
|
+
await sleep(1000);
|
|
932
|
+
test_result = await post(
|
|
933
|
+
`/deploy/solutions/${solution_id}/skills/${skill_id}/test`,
|
|
934
|
+
{ message: test_message },
|
|
935
|
+
sid,
|
|
936
|
+
{ timeoutMs: 90_000 },
|
|
937
|
+
);
|
|
938
|
+
phases.push({ phase: "test", status: "done" });
|
|
939
|
+
} catch (err) {
|
|
940
|
+
test_result = { error: err.message };
|
|
941
|
+
phases.push({ phase: "test", status: "error", error: err.message });
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
return {
|
|
946
|
+
ok: true,
|
|
947
|
+
solution_id,
|
|
948
|
+
phases,
|
|
949
|
+
patch: patchResult,
|
|
950
|
+
redeploy: redeployResult,
|
|
951
|
+
...(test_result && { test_result }),
|
|
952
|
+
};
|
|
953
|
+
},
|
|
954
|
+
|
|
955
|
+
// ─── Original handlers (unchanged) ────────────────────────────────
|
|
956
|
+
|
|
640
957
|
ateam_validate_skill: async ({ skill }, sid) => post("/validate/skill", { skill }, sid),
|
|
641
958
|
|
|
642
959
|
ateam_validate_solution: async ({ solution, skills }, sid) =>
|
|
@@ -820,21 +1137,28 @@ export async function handleToolCall(name, args, sessionId) {
|
|
|
820
1137
|
};
|
|
821
1138
|
}
|
|
822
1139
|
|
|
823
|
-
// Check auth for
|
|
824
|
-
|
|
1140
|
+
// Check auth for tenant-aware operations — requires explicit ateam_auth call.
|
|
1141
|
+
// Env vars (ADAS_API_KEY / ADAS_TENANT) are NOT sufficient — they may be
|
|
1142
|
+
// baked into MCP config and silently target the wrong tenant.
|
|
1143
|
+
// Only global/public tools (bootstrap, spec, examples, validate) bypass this.
|
|
1144
|
+
if (TENANT_TOOLS.has(name) && !isExplicitlyAuthenticated(sessionId)) {
|
|
1145
|
+
const hasEnvVars = isAuthenticated(sessionId);
|
|
825
1146
|
return {
|
|
826
1147
|
content: [{
|
|
827
1148
|
type: "text",
|
|
828
1149
|
text: [
|
|
829
|
-
"
|
|
1150
|
+
"Authentication required — call ateam_auth first.",
|
|
830
1151
|
"",
|
|
831
|
-
|
|
1152
|
+
hasEnvVars
|
|
1153
|
+
? "Environment variables (ADAS_API_KEY) were detected, but they are not sufficient for tenant-aware operations. You must call ateam_auth explicitly to confirm which tenant you intend to use."
|
|
1154
|
+
: "No authentication found.",
|
|
832
1155
|
"",
|
|
1156
|
+
"Please ask the user to:",
|
|
833
1157
|
"1. Get their API key at: https://mcp.ateam-ai.com/get-api-key",
|
|
834
1158
|
"2. Then call: ateam_auth(api_key: \"<their key>\")",
|
|
835
1159
|
"",
|
|
836
|
-
"The key
|
|
837
|
-
"
|
|
1160
|
+
"The key format is: adas_<tenant>_<32hex> — the tenant is auto-extracted.",
|
|
1161
|
+
"This prevents accidental operations on the wrong tenant from pre-configured env vars.",
|
|
838
1162
|
].join("\n"),
|
|
839
1163
|
}],
|
|
840
1164
|
isError: true,
|