@ateam-ai/mcp 0.4.77 → 0.4.78

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 (3) hide show
  1. package/package.json +1 -1
  2. package/src/api.js +24 -0
  3. package/src/tools.js +24 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.4.77",
3
+ "version": "0.4.78",
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
@@ -487,6 +487,30 @@ function formatError(method, path, status, body, baseUrl) {
487
487
  503: "A-Team API is temporarily unavailable. Try again in a minute.",
488
488
  };
489
489
 
490
+ // A 401 IS NOT ALWAYS AN AUTH PROBLEM, AND SAYING SO COSTS A RUN.
491
+ //
492
+ // The table below attaches "your API key may be invalid or expired — get a
493
+ // new key and call ateam_auth" to EVERY 401, by status code, never by cause.
494
+ // Core also returns 401 for `Actor "X" not found`, where the key is perfectly
495
+ // valid and the actor is the problem. A PROD agent believed that hint this
496
+ // morning, stopped, and asked the admin to paste an API key — for an error
497
+ // that had nothing to do with keys. An error naming the wrong remedy does not
498
+ // just fail; it sends someone competent in the wrong direction.
499
+ if (status === 401) {
500
+ const t = typeof body === "string"
501
+ ? body
502
+ : (() => { try { return JSON.stringify(body || ""); } catch { return ""; } })();
503
+ const m = /Actor\s+\\?"([^"\\]+)\\?"\s+not found|unknown actor\s+\\?"?([^"\\,}]+)/i.exec(t);
504
+ if (m) {
505
+ const who = (m[1] || m[2] || "").trim();
506
+ hints[401] =
507
+ `NOT an auth problem — your key is fine. Core does not recognise the ACTOR "${who}" in this tenant. ` +
508
+ `Re-authenticating will not help. Either pass a real actor id (the one ateam_conversation returned for the thread), ` +
509
+ `or omit the actor entirely to act as the tenant. If you never sent an actor, the session is bound to a stale one: ` +
510
+ `call ateam_auth again to reset the session binding.`;
511
+ }
512
+ }
513
+
490
514
  // A 500 THAT NAMES A MISSING CONFIGURATION IS NOT "TRY AGAIN IN A MINUTE".
491
515
  //
492
516
  // /chat answered 500 {"message":"OPENAI_API_KEY is not set"} and this table
package/src/tools.js CHANGED
@@ -19,6 +19,17 @@ import {
19
19
  // (tenant + the app URL to view the change). ateam-mcp is a PUBLIC MCP used
20
20
  // from non-desktop clients too, so the location must live IN the tool result
21
21
  // — not only in a desktop plugin's SKILL.md. Read-only/global tools skip it.
22
+ // Tools that START a run and therefore MINT the actor that ran it. Only these
23
+ // may rebind the session's actor — see the call site for what accepting it from
24
+ // any result cost.
25
+ const ACTOR_MINTING_TOOLS = new Set([
26
+ "ateam_conversation",
27
+ "ateam_test_skill",
28
+ "ateam_solution_chat",
29
+ "ateam_test_pipeline",
30
+ "ateam_test_voice",
31
+ ]);
32
+
22
33
  const STAMP_WHERE_TOOLS = new Set([
23
34
  "ateam_build_and_run", "ateam_patch", "ateam_upload_connector", "ateam_redeploy",
24
35
  "ateam_create_skill", "ateam_create_connector", "ateam_create_plugin",
@@ -6129,7 +6140,19 @@ export async function handleToolCall(name, args, sessionId) {
6129
6140
  // it on the way out so the follow-up ateam_get_execution_logs /
6130
6141
  // ateam_get_metrics on that very job is not refused for not knowing who ran
6131
6142
  // it — the single most common dead end when debugging a run.
6132
- if (result && typeof result === "object" && result.actor_id) {
6143
+ //
6144
+ // ONLY FROM TOOLS THAT ACTUALLY MINT ONE. This used to accept `actor_id` off
6145
+ // ANY tool's result, so a single unrelated payload carrying that field
6146
+ // silently repointed the whole session — observed on a clean e2e where every
6147
+ // later call 401'd with `Actor "dev" not found`, from an agent that had
6148
+ // never sent an actor at all. A session that binds to a non-existent actor
6149
+ // never recovers on its own, because nothing ever unbinds it.
6150
+ //
6151
+ // The generated-thread-key filter in api.js does not help here: it rejects
6152
+ // test_<ts>_<rand>, and a short literal like "dev" walks straight past it.
6153
+ // An allow-list of minting tools is the honest boundary — "who ran this job"
6154
+ // is knowledge only the tools that START a job possess.
6155
+ if (result && typeof result === "object" && result.actor_id && ACTOR_MINTING_TOOLS.has(name)) {
6133
6156
  touchSession(sessionId, { actorId: result.actor_id });
6134
6157
  }
6135
6158