@ateam-ai/mcp 0.4.74 → 0.4.75

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 +54 -26
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ateam-ai/mcp",
3
- "version": "0.4.74",
3
+ "version": "0.4.75",
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
@@ -239,47 +239,75 @@ function _widgetHasRender(r) {
239
239
  //
240
240
  // Detected here rather than left to a person noticing an empty panel, and
241
241
  // reported with the repair attached — a signal the reasoning engine can act on.
242
+ // Extract the FULL argument object of each postMessage(...) call by matching
243
+ // braces, so every call is judged on its own text. The previous version took a
244
+ // fixed 400-character window and concatenated all of them: a send object longer
245
+ // than the window was inspected in part, and `source:"adas-plugin"` in one call
246
+ // could make an unrelated postMessage elsewhere on the page be judged as the
247
+ // ADAS protocol. Both were rejected in review, correctly — an approximate
248
+ // boundary is not a structural one.
249
+ function _postMessageObjects(html) {
250
+ const out = [];
251
+ const re = /postMessage\s*\(\s*\{/g;
252
+ let m;
253
+ while ((m = re.exec(html)) !== null) {
254
+ const open = html.indexOf("{", m.index);
255
+ let depth = 0, i = open, inStr = null, esc = false;
256
+ for (; i < html.length; i++) {
257
+ const c = html[i];
258
+ if (inStr) {
259
+ if (esc) { esc = false; continue; }
260
+ if (c === "\\") { esc = true; continue; }
261
+ if (c === inStr) inStr = null;
262
+ continue;
263
+ }
264
+ if (c === '"' || c === "'" || c === "`") { inStr = c; continue; }
265
+ if (c === "{") depth++;
266
+ else if (c === "}") { depth--; if (depth === 0) { i++; break; } }
267
+ }
268
+ // Unbalanced (minified truncation, template weirdness) → skip rather than
269
+ // guess. A message we cannot delimit is one we must not judge.
270
+ if (depth === 0) out.push(html.slice(open, i));
271
+ re.lastIndex = Math.max(re.lastIndex, i);
272
+ }
273
+ return out;
274
+ }
275
+
242
276
  export function _widgetProtocolProblems(html) {
243
277
  if (typeof html !== "string" || !html.includes("postMessage")) return [];
244
278
 
245
- // STRUCTURE, NOT TOKENS. The first version matched /correlationId/ anywhere in
246
- // the file, so a correct widget with an unrelated local named correlationId was
247
- // reported broken — and `fix_with` would then steer an agent into editing
248
- // working code. Reviewer was right to reject it. Each check below anchors to
249
- // the actual send or receive shape.
250
279
  const problems = [];
251
-
252
- // Only look at what is POSTED to the host: postMessage(...) argument objects.
253
- const sends = [...html.matchAll(/postMessage\s*\(\s*\{[\s\S]{0,400}/g)].map((m) => m[0]);
254
- const sendBlob = sends.join("\n");
255
- const isPluginSend = /source\s*:\s*["']adas-plugin["']/.test(sendBlob);
256
-
257
- if (isPluginSend) {
258
- if (/type\s*:\s*["']tool\.call["']/.test(sendBlob)) {
259
- problems.push('sends message.type:"tool.call" — the host has NEVER accepted it, at any version (silent timeout, no error). Send message:{action:"mcp-call",payload:{requestId,connectorId,tool,args}}.');
260
- } else if (!/action\s*:\s*["']mcp-call["']/.test(sendBlob)) {
261
- // type:"mcp-call" is the near-miss worth naming separately: right name,
262
- // wrong key. The host matches on message.action and ignores message.type.
263
- if (/type\s*:\s*["']mcp-call["']/.test(sendBlob)) {
264
- problems.push('sends message.TYPE:"mcp-call" — the host matches on message.ACTION for sends, so this is ignored. Use message:{action:"mcp-call",payload:{...}}.');
280
+ const seen = new Set();
281
+ const add = (p) => { if (!seen.has(p)) { seen.add(p); problems.push(p); } };
282
+
283
+ // Judge each host-directed send INDEPENDENTLY. A page may legitimately
284
+ // postMessage to other targets; only objects that identify themselves as the
285
+ // ADAS plugin channel are the protocol.
286
+ for (const obj of _postMessageObjects(html)) {
287
+ if (!/source\s*:\s*["']adas-plugin["']/.test(obj)) continue;
288
+
289
+ if (/type\s*:\s*["']tool\.call["']/.test(obj)) {
290
+ add('sends message.type:"tool.call" the host has NEVER accepted it, at any version (silent timeout, no error). Send message:{action:"mcp-call",payload:{requestId,connectorId,tool,args}}.');
291
+ } else if (!/action\s*:\s*["']mcp-call["']/.test(obj)) {
292
+ if (/type\s*:\s*["']mcp-call["']/.test(obj)) {
293
+ add('sends message.TYPE:"mcp-call" — the host matches on message.ACTION for sends, so this is ignored. Use message:{action:"mcp-call",payload:{...}}.');
265
294
  } else {
266
- problems.push('never sends action:"mcp-call" — the host ignores the message entirely.');
295
+ add('never sends action:"mcp-call" — the host ignores the message entirely.');
267
296
  }
268
297
  }
269
- // correlationId only counts as a defect where it carries the request id.
270
- if (/payload\s*:\s*\{[^}]*correlationId/.test(sendBlob) || /correlationId\s*:\s*correlationId/.test(sendBlob)) {
271
- problems.push('sends the request id as correlationId — the host echoes payload.requestId, so responses never match the pending request and every call times out even when the host answered.');
298
+ if (/payload\s*:\s*\{[^}]*correlationId/.test(obj) || /correlationId\s*:\s*correlationId/.test(obj)) {
299
+ add('sends the request id as correlationId the host echoes payload.requestId, so responses never match the pending request and every call times out even when the host answered.');
272
300
  }
273
301
  }
274
302
 
275
- // RECEIVE side: only flag reading correlationId OFF THE HOST PAYLOAD.
303
+ // RECEIVE side: only reading correlationId OFF THE HOST PAYLOAD counts.
276
304
  if (/payload\s*(\?\.|\.)\s*correlationId/.test(html) ||
277
305
  /payload\s*&&\s*[\w$.]*payload\.correlationId/.test(html) ||
278
306
  /\{\s*correlationId[^}]*\}\s*=\s*[\w$.]*payload/.test(html)) {
279
- problems.push('reads payload.correlationId from the host response — the host sends payload.requestId, so the pending request is never matched.');
307
+ add('reads payload.correlationId from the host response — the host sends payload.requestId, so the pending request is never matched.');
280
308
  }
281
309
  if (/type\s*===?\s*["']tool\.response["']/.test(html)) {
282
- problems.push('listens for message.type:"tool.response" — the host replies with "mcp-result".');
310
+ add('listens for message.type:"tool.response" — the host replies with "mcp-result".');
283
311
  }
284
312
 
285
313
  return problems;