@ateam-ai/mcp 0.4.53 → 0.4.57
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/tools.js +120 -2
package/package.json
CHANGED
package/src/tools.js
CHANGED
|
@@ -1017,6 +1017,59 @@ export const tools = [
|
|
|
1017
1017
|
},
|
|
1018
1018
|
},
|
|
1019
1019
|
|
|
1020
|
+
{
|
|
1021
|
+
name: "ateam_log_lesson",
|
|
1022
|
+
core: true,
|
|
1023
|
+
description:
|
|
1024
|
+
"Record ONE lesson this run learned, so the NEXT run does not relearn it. " +
|
|
1025
|
+
"A building agent starts every run empty — it does not know which tool " +
|
|
1026
|
+
"misled the last run or the workaround that got past it. Log a lesson the " +
|
|
1027
|
+
"moment a tool misleads you AND you find a way through.\n\n" +
|
|
1028
|
+
"APPEND-ONLY. You cannot edit or delete earlier lessons, and you do not " +
|
|
1029
|
+
"supply the timestamp, job or actor — the server stamps those.\n\n" +
|
|
1030
|
+
"LOG ONLY WHAT YOU OBSERVED. Quote the error VERBATIM; never paraphrase it " +
|
|
1031
|
+
"and never write a theory about platform internals. A wrong lesson is worse " +
|
|
1032
|
+
"than no lesson, because the next run cannot check it and will act on it.\n\n" +
|
|
1033
|
+
"Use kind='misleading_success' when a call REPORTED success while the thing " +
|
|
1034
|
+
"you wanted did not happen — that class is the most expensive to rediscover " +
|
|
1035
|
+
"and it is invisible to a failures-only log.",
|
|
1036
|
+
inputSchema: {
|
|
1037
|
+
type: "object",
|
|
1038
|
+
properties: {
|
|
1039
|
+
solution_id: { type: "string", description: "The solution this lesson belongs to" },
|
|
1040
|
+
tool: { type: "string", description: "The tool that misled you, e.g. \"ateam_build_and_run\"" },
|
|
1041
|
+
error: { type: "string", description: "The VERBATIM error or failed_steps fragment. Not a paraphrase." },
|
|
1042
|
+
workaround: { type: "string", description: "What you did instead (optional)" },
|
|
1043
|
+
worked: { type: "boolean", description: "Did the workaround work? Omit if you never found out — 'unknown' is a real answer" },
|
|
1044
|
+
kind: {
|
|
1045
|
+
type: "string",
|
|
1046
|
+
enum: ["failure", "surprise", "misleading_success"],
|
|
1047
|
+
description: "failure = it errored; surprise = it worked but not as documented; misleading_success = it REPORTED success while the intended effect did not happen",
|
|
1048
|
+
},
|
|
1049
|
+
},
|
|
1050
|
+
required: ["solution_id", "tool", "error"],
|
|
1051
|
+
},
|
|
1052
|
+
},
|
|
1053
|
+
|
|
1054
|
+
{
|
|
1055
|
+
name: "ateam_get_lessons",
|
|
1056
|
+
core: true,
|
|
1057
|
+
description:
|
|
1058
|
+
"Read what EARLIER runs on this solution learned — newest first, bounded. " +
|
|
1059
|
+
"Call this during orientation, BEFORE planning: it is the only thing that " +
|
|
1060
|
+
"carries context across runs, and it is cheap. Each entry says which tool " +
|
|
1061
|
+
"misled a previous run, the verbatim error, what was tried instead, and " +
|
|
1062
|
+
"whether that worked. An empty list is a real answer (nothing learned yet).",
|
|
1063
|
+
inputSchema: {
|
|
1064
|
+
type: "object",
|
|
1065
|
+
properties: {
|
|
1066
|
+
solution_id: { type: "string", description: "The solution ID" },
|
|
1067
|
+
limit: { type: "number", description: "Max entries, newest first (default 20)" },
|
|
1068
|
+
},
|
|
1069
|
+
required: ["solution_id"],
|
|
1070
|
+
},
|
|
1071
|
+
},
|
|
1072
|
+
|
|
1020
1073
|
{
|
|
1021
1074
|
name: "ateam_create_connector",
|
|
1022
1075
|
core: true,
|
|
@@ -2287,7 +2340,22 @@ function toText(data) { return { content: [{ type: "text", text: JSON.stringify(
|
|
|
2287
2340
|
// into the call args; refuse to operate without it (prevents cross-actor leaks).
|
|
2288
2341
|
function getActorId(args) {
|
|
2289
2342
|
const id = args?._adas_actor;
|
|
2290
|
-
|
|
2343
|
+
// Name BOTH causes. "actor context missing" reads as "Core did not send it",
|
|
2344
|
+
// and that misreading cost a full day on 2026-08-20: Core HAD injected it and
|
|
2345
|
+
// the connector's own schema validation stripped it, because that one tool's
|
|
2346
|
+
// inputSchema omitted _adas_actor. An MCP server drops arguments a tool did
|
|
2347
|
+
// not declare, so the field vanishes silently — and only on the tools that
|
|
2348
|
+
// forgot it, which is why read tools kept working and the first write failed.
|
|
2349
|
+
if (!id) {
|
|
2350
|
+
throw new Error(
|
|
2351
|
+
"${connectorId}: no actor context — _adas_actor missing. TWO possible causes: " +
|
|
2352
|
+
"(1) this tool's inputSchema does not DECLARE _adas_actor, so MCP stripped it " +
|
|
2353
|
+
"before your handler ran — add it to inputSchema.properties (see toolSchemas() " +
|
|
2354
|
+
"below, every data tool must spread ...actor); or " +
|
|
2355
|
+
"(2) the caller is not actor-scoped — ateam_test_connector runs as _system_service, " +
|
|
2356
|
+
"so use ateam_test_skill or a real conversation to exercise per-user tools."
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2291
2359
|
return id;
|
|
2292
2360
|
}
|
|
2293
2361
|
${uiCapable ? `
|
|
@@ -2317,6 +2385,13 @@ function discoverPlugins() {
|
|
|
2317
2385
|
// ── Tool definitions ── Core reads this list. A tool named "ui.listPlugins"
|
|
2318
2386
|
// is how Core knows this connector is UI-capable.
|
|
2319
2387
|
function toolSchemas() {
|
|
2388
|
+
// MUST be spread into the inputSchema.properties of EVERY per-actor tool.
|
|
2389
|
+
// Not decoration: MCP strips arguments a tool did not declare, so a tool that
|
|
2390
|
+
// omits these gets them removed before the handler runs and getActorId()
|
|
2391
|
+
// throws — while the tools that DID declare them keep working. The result is
|
|
2392
|
+
// a connector that looks healthy (deploys, lists tools, answers reads) and
|
|
2393
|
+
// fails on the first write. Do not "fix" that with a default actor id: one
|
|
2394
|
+
// shared actor pools every user's data.
|
|
2320
2395
|
const actor = { _adas_actor: { type: "string" }, _adas_tenant: { type: "string" } };
|
|
2321
2396
|
return [
|
|
2322
2397
|
{
|
|
@@ -2340,7 +2415,33 @@ async function handle(req) {
|
|
|
2340
2415
|
|
|
2341
2416
|
if (method === "tools/call") {
|
|
2342
2417
|
const name = params?.name;
|
|
2343
|
-
|
|
2418
|
+
// CALLER CONTEXT COMES FROM THE ENVELOPE FIRST.
|
|
2419
|
+
//
|
|
2420
|
+
// Core sends identity two ways: as _adas_* ARGUMENTS, and on params._meta
|
|
2421
|
+
// beside the arguments object. The argument channel is fragile — a server drops
|
|
2422
|
+
// arguments a tool did not declare, so a tool whose inputSchema omits
|
|
2423
|
+
// _adas_actor loses it silently and only per-user WRITES fail, while reads
|
|
2424
|
+
// keep working. The envelope cannot be stripped: it is not part of the
|
|
2425
|
+
// validated argument object.
|
|
2426
|
+
//
|
|
2427
|
+
// This server reads params directly (no SDK zod validation), so _meta is
|
|
2428
|
+
// simply available — no wrapper, no callback plumbing. Merge it UNDER args
|
|
2429
|
+
// so an explicitly declared argument still wins, which keeps a delegation
|
|
2430
|
+
// tool's own actor_id PARAMETER untouched: caller identity is transport,
|
|
2431
|
+
// subject identity is payload, and they must not collide.
|
|
2432
|
+
//
|
|
2433
|
+
// ONLY the _adas_ prefix. _meta is the MCP envelope's OWN namespace, not
|
|
2434
|
+
// ours — the spec puts progressToken in there, and clients that request
|
|
2435
|
+
// progress send it on every call. Spreading the whole envelope would hand a
|
|
2436
|
+
// transport token to tools as a user argument: schemas with
|
|
2437
|
+
// additionalProperties:false would start rejecting previously-valid calls,
|
|
2438
|
+
// tools that log or persist their arguments would record it as user data,
|
|
2439
|
+
// and a future _meta key colliding with a real parameter name would
|
|
2440
|
+
// overwrite it. Read the namespace we own; do not treat the envelope as input.
|
|
2441
|
+
const ctx = Object.fromEntries(
|
|
2442
|
+
Object.entries(params?._meta || {}).filter(([k]) => k.startsWith("_adas_")),
|
|
2443
|
+
);
|
|
2444
|
+
const args = { ...ctx, ...(params?.arguments || {}) };
|
|
2344
2445
|
try {
|
|
2345
2446
|
${uiCapable ? ` // ── UI registry plumbing (no actor required) ──
|
|
2346
2447
|
if (name === "ui.listPlugins") {
|
|
@@ -4954,6 +5055,23 @@ const handlers = {
|
|
|
4954
5055
|
};
|
|
4955
5056
|
},
|
|
4956
5057
|
|
|
5058
|
+
ateam_log_lesson: async ({ solution_id, tool, error, workaround, worked, kind }, sid) => {
|
|
5059
|
+
if (!solution_id) throw new Error("solution_id required");
|
|
5060
|
+
if (!tool) throw new Error("tool required — the tool that misled you");
|
|
5061
|
+
if (!error) throw new Error("error required — quote it VERBATIM, do not paraphrase");
|
|
5062
|
+
return await post(
|
|
5063
|
+
`/solutions/${solution_id}/lessons`,
|
|
5064
|
+
{ tool, error, workaround, worked, kind },
|
|
5065
|
+
sid,
|
|
5066
|
+
);
|
|
5067
|
+
},
|
|
5068
|
+
|
|
5069
|
+
ateam_get_lessons: async ({ solution_id, limit }, sid) => {
|
|
5070
|
+
if (!solution_id) throw new Error("solution_id required");
|
|
5071
|
+
const qs = Number.isFinite(limit) ? `?limit=${limit}` : "";
|
|
5072
|
+
return await get(`/solutions/${solution_id}/lessons${qs}`, sid);
|
|
5073
|
+
},
|
|
5074
|
+
|
|
4957
5075
|
ateam_show_solution_minimal: async ({ solution_id }, sid) => {
|
|
4958
5076
|
if (!solution_id) throw new Error("solution_id required");
|
|
4959
5077
|
const full = await get(`/deploy/solutions/${solution_id}/definition`, sid);
|