@integrity-labs/agt-cli 0.28.522 → 0.28.524

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.
@@ -32596,7 +32596,14 @@ var REMOTE_MCP_PROXY_ENV = {
32596
32596
  authHeader: "AGT_REMOTE_MCP_AUTH_HEADER",
32597
32597
  extraHeaders: "AGT_REMOTE_MCP_EXTRA_HEADERS",
32598
32598
  toolAllowlist: "AGT_REMOTE_MCP_TOOL_ALLOWLIST",
32599
- preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS"
32599
+ preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS",
32600
+ // ENG-8512: per-provider argument rules. A `tools/call` carrying a value we
32601
+ // KNOW the remote accepts and silently ignores is refused before it is
32602
+ // forwarded, rather than returning a 200 that every layer above records as
32603
+ // success. Deliberately NOT in REMOTE_MCP_AUTH_ENV_KEYS: it shapes which calls
32604
+ // we forward, not what an outbound request looks like, so the probe (which
32605
+ // never issues a tools/call) has nothing to reconstruct from it.
32606
+ argRejects: "AGT_REMOTE_MCP_ARG_REJECTS"
32600
32607
  };
32601
32608
  var REMOTE_MCP_AUTH_ENV_KEYS = [
32602
32609
  REMOTE_MCP_PROXY_ENV.tokenVar,
@@ -38934,7 +38934,14 @@ var REMOTE_MCP_PROXY_ENV = {
38934
38934
  authHeader: "AGT_REMOTE_MCP_AUTH_HEADER",
38935
38935
  extraHeaders: "AGT_REMOTE_MCP_EXTRA_HEADERS",
38936
38936
  toolAllowlist: "AGT_REMOTE_MCP_TOOL_ALLOWLIST",
38937
- preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS"
38937
+ preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS",
38938
+ // ENG-8512: per-provider argument rules. A `tools/call` carrying a value we
38939
+ // KNOW the remote accepts and silently ignores is refused before it is
38940
+ // forwarded, rather than returning a 200 that every layer above records as
38941
+ // success. Deliberately NOT in REMOTE_MCP_AUTH_ENV_KEYS: it shapes which calls
38942
+ // we forward, not what an outbound request looks like, so the probe (which
38943
+ // never issues a tools/call) has nothing to reconstruct from it.
38944
+ argRejects: "AGT_REMOTE_MCP_ARG_REJECTS"
38938
38945
  };
38939
38946
  var REMOTE_MCP_AUTH_ENV_KEYS = [
38940
38947
  REMOTE_MCP_PROXY_ENV.tokenVar,
@@ -17,7 +17,14 @@ var REMOTE_MCP_PROXY_ENV = {
17
17
  authHeader: "AGT_REMOTE_MCP_AUTH_HEADER",
18
18
  extraHeaders: "AGT_REMOTE_MCP_EXTRA_HEADERS",
19
19
  toolAllowlist: "AGT_REMOTE_MCP_TOOL_ALLOWLIST",
20
- preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS"
20
+ preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS",
21
+ // ENG-8512: per-provider argument rules. A `tools/call` carrying a value we
22
+ // KNOW the remote accepts and silently ignores is refused before it is
23
+ // forwarded, rather than returning a 200 that every layer above records as
24
+ // success. Deliberately NOT in REMOTE_MCP_AUTH_ENV_KEYS: it shapes which calls
25
+ // we forward, not what an outbound request looks like, so the probe (which
26
+ // never issues a tools/call) has nothing to reconstruct from it.
27
+ argRejects: "AGT_REMOTE_MCP_ARG_REJECTS"
21
28
  };
22
29
  var REMOTE_MCP_AUTH_ENV_KEYS = [
23
30
  REMOTE_MCP_PROXY_ENV.tokenVar,
@@ -67,6 +74,7 @@ var TOKEN_FILE_ENV = REMOTE_MCP_PROXY_ENV.tokenFile;
67
74
  var TOKEN_VAR_ENV = REMOTE_MCP_PROXY_ENV.tokenVar;
68
75
  var ALLOWLIST_ENV = REMOTE_MCP_PROXY_ENV.toolAllowlist;
69
76
  var PREENABLE_ENV = REMOTE_MCP_PROXY_ENV.preEnableToolsets;
77
+ var ARG_REJECTS_ENV = REMOTE_MCP_PROXY_ENV.argRejects;
70
78
  var REMOTE_FETCH_TIMEOUT_MS = 3e4;
71
79
  var remoteUrl = process.env[URL_ENV] ?? "";
72
80
  var tokenFile = process.env[TOKEN_FILE_ENV] ?? "";
@@ -74,6 +82,7 @@ var tokenVar = process.env[TOKEN_VAR_ENV] ?? "";
74
82
  var label = process.env[REMOTE_MCP_PROXY_ENV.label] || tokenVar || "remote-oauth";
75
83
  var toolAllowlist = parseToolAllowlist(process.env[ALLOWLIST_ENV] ?? "");
76
84
  var preEnableToolsets = parsePreEnableToolsets(process.env[PREENABLE_ENV] ?? "");
85
+ var argRejects = parseArgRejects(process.env[ARG_REJECTS_ENV] ?? "");
77
86
  var { authHeader: authHeaderName, extras: extraHeaderSpecs } = readRemoteMcpAuthConfig(process.env);
78
87
  function logErr(msg) {
79
88
  process.stderr.write(`[remote-oauth-proxy:${label}] ${msg}
@@ -183,6 +192,70 @@ function isToolCallBlocked(method, params, allow) {
183
192
  if (name && !allow.has(name)) return { blocked: true, name };
184
193
  return { blocked: false, name };
185
194
  }
195
+ function parseArgRejects(raw) {
196
+ if (!raw || !raw.trim()) return [];
197
+ let parsed;
198
+ try {
199
+ parsed = JSON.parse(raw);
200
+ } catch {
201
+ return [];
202
+ }
203
+ if (!Array.isArray(parsed)) return [];
204
+ const out = [];
205
+ for (const entry of parsed) {
206
+ if (!entry || typeof entry !== "object") continue;
207
+ const e = entry;
208
+ const tool = typeof e["tool"] === "string" ? e["tool"] : "";
209
+ const field = typeof e["field"] === "string" ? e["field"] : "";
210
+ const pattern = typeof e["pattern"] === "string" ? e["pattern"] : "";
211
+ const message = typeof e["message"] === "string" ? e["message"] : "";
212
+ if (!tool || !field || !pattern || !message) continue;
213
+ try {
214
+ out.push({ tool, field, re: new RegExp(pattern), message });
215
+ } catch {
216
+ }
217
+ }
218
+ return out;
219
+ }
220
+ function isToolArgRejected(method, params, rules) {
221
+ const none = { rejected: false, name: "", field: "", message: "" };
222
+ if (rules.length === 0 || method !== "tools/call") return none;
223
+ if (!params || typeof params !== "object") return none;
224
+ const p = params;
225
+ const name = typeof p.name === "string" ? p.name : "";
226
+ if (!name) return none;
227
+ const args = p.arguments;
228
+ if (!args || typeof args !== "object") return none;
229
+ const bag = args;
230
+ for (const rule of rules) {
231
+ if (rule.tool !== name) continue;
232
+ const value = bag[rule.field];
233
+ if (typeof value !== "string") continue;
234
+ if (rule.re.test(value)) {
235
+ return { rejected: true, name, field: rule.field, message: rule.message };
236
+ }
237
+ }
238
+ return none;
239
+ }
240
+ function callRefusal(method, params, allow, rules, label2) {
241
+ const block = isToolCallBlocked(method, params, allow);
242
+ if (block.blocked) {
243
+ return {
244
+ log: `blocked tools/call to non-allowlisted tool "${block.name}"`,
245
+ code: -32601,
246
+ message: `${label2}: tool "${block.name}" is not enabled for this integration`
247
+ };
248
+ }
249
+ const argReject = isToolArgRejected(method, params, rules);
250
+ if (argReject.rejected) {
251
+ return {
252
+ log: `rejected tools/call "${argReject.name}": argument "${argReject.field}" would be silently ignored by the remote`,
253
+ code: -32602,
254
+ message: `${label2}: ${argReject.name} refused - ${argReject.message}`
255
+ };
256
+ }
257
+ return null;
258
+ }
186
259
  function readCurrentToken(file, varName) {
187
260
  let raw;
188
261
  try {
@@ -426,17 +499,16 @@ async function main() {
426
499
  }
427
500
  const isNotification = !("id" in parsed);
428
501
  const id = parsed.id;
429
- if (!isNotification) {
430
- const block = isToolCallBlocked(parsed.method, parsed.params, toolAllowlist);
431
- if (block.blocked) {
432
- logErr(`blocked tools/call to non-allowlisted tool "${block.name}"`);
433
- const task2 = writeReplies([
434
- jsonRpcError(id, -32601, `${label}: tool "${block.name}" is not enabled for this integration`)
435
- ]).catch((err) => logErr(`handler error: ${err.message}`));
436
- inflight.add(task2);
437
- void task2.finally(() => inflight.delete(task2));
438
- return;
439
- }
502
+ const refusal = callRefusal(parsed.method, parsed.params, toolAllowlist, argRejects, label);
503
+ if (refusal) {
504
+ logErr(isNotification ? `${refusal.log} (notification, no reply sent)` : refusal.log);
505
+ if (isNotification) return;
506
+ const task2 = writeReplies([jsonRpcError(id, refusal.code, refusal.message)]).catch(
507
+ (err) => logErr(`handler error: ${err.message}`)
508
+ );
509
+ inflight.add(task2);
510
+ void task2.finally(() => inflight.delete(task2));
511
+ return;
440
512
  }
441
513
  const task = forward(text, id, isNotification, parsed.method, parsed.params).then(writeReplies).catch((err) => {
442
514
  logErr(`handler error: ${err.message}`);
@@ -466,13 +538,16 @@ export {
466
538
  buildEnableToolsetRequest,
467
539
  buildForwardHeaders,
468
540
  buildToolsListRequest,
541
+ callRefusal,
469
542
  extractJsonRpcMessages,
470
543
  extractToolsArray,
471
544
  filterToolsListMessage,
472
545
  forward,
473
546
  isManagedActivationCall,
547
+ isToolArgRejected,
474
548
  isToolCallBlocked,
475
549
  main,
550
+ parseArgRejects,
476
551
  parseEnableToolsetResponse,
477
552
  parseExtraHeaders,
478
553
  parsePreEnableToolsets,
@@ -32818,7 +32818,14 @@ var REMOTE_MCP_PROXY_ENV = {
32818
32818
  authHeader: "AGT_REMOTE_MCP_AUTH_HEADER",
32819
32819
  extraHeaders: "AGT_REMOTE_MCP_EXTRA_HEADERS",
32820
32820
  toolAllowlist: "AGT_REMOTE_MCP_TOOL_ALLOWLIST",
32821
- preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS"
32821
+ preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS",
32822
+ // ENG-8512: per-provider argument rules. A `tools/call` carrying a value we
32823
+ // KNOW the remote accepts and silently ignores is refused before it is
32824
+ // forwarded, rather than returning a 200 that every layer above records as
32825
+ // success. Deliberately NOT in REMOTE_MCP_AUTH_ENV_KEYS: it shapes which calls
32826
+ // we forward, not what an outbound request looks like, so the probe (which
32827
+ // never issues a tools/call) has nothing to reconstruct from it.
32828
+ argRejects: "AGT_REMOTE_MCP_ARG_REJECTS"
32822
32829
  };
32823
32830
  var REMOTE_MCP_AUTH_ENV_KEYS = [
32824
32831
  REMOTE_MCP_PROXY_ENV.tokenVar,
@@ -33144,7 +33144,14 @@ var REMOTE_MCP_PROXY_ENV = {
33144
33144
  authHeader: "AGT_REMOTE_MCP_AUTH_HEADER",
33145
33145
  extraHeaders: "AGT_REMOTE_MCP_EXTRA_HEADERS",
33146
33146
  toolAllowlist: "AGT_REMOTE_MCP_TOOL_ALLOWLIST",
33147
- preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS"
33147
+ preEnableToolsets: "AGT_REMOTE_MCP_PREENABLE_TOOLSETS",
33148
+ // ENG-8512: per-provider argument rules. A `tools/call` carrying a value we
33149
+ // KNOW the remote accepts and silently ignores is refused before it is
33150
+ // forwarded, rather than returning a 200 that every layer above records as
33151
+ // success. Deliberately NOT in REMOTE_MCP_AUTH_ENV_KEYS: it shapes which calls
33152
+ // we forward, not what an outbound request looks like, so the probe (which
33153
+ // never issues a tools/call) has nothing to reconstruct from it.
33154
+ argRejects: "AGT_REMOTE_MCP_ARG_REJECTS"
33148
33155
  };
33149
33156
  var REMOTE_MCP_AUTH_ENV_KEYS = [
33150
33157
  REMOTE_MCP_PROXY_ENV.tokenVar,
@@ -37,7 +37,7 @@ import {
37
37
  writeDirectChatSessionState,
38
38
  writeEgressAllowlist,
39
39
  writePersistentClaudeWrapper
40
- } from "./chunk-4GTDD2I5.js";
40
+ } from "./chunk-LBSV575W.js";
41
41
  import "./chunk-XWVM4KPK.js";
42
42
  export {
43
43
  EGRESS_BASELINE_DOMAINS,
@@ -79,4 +79,4 @@ export {
79
79
  writeEgressAllowlist,
80
80
  writePersistentClaudeWrapper
81
81
  };
82
- //# sourceMappingURL=persistent-session-5GMZKV37.js.map
82
+ //# sourceMappingURL=persistent-session-OT66RBK5.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-4GTDD2I5.js";
3
+ } from "./chunk-LBSV575W.js";
4
4
  import "./chunk-XWVM4KPK.js";
5
5
 
6
6
  // src/lib/responsiveness-probe.ts
@@ -662,4 +662,4 @@ export {
662
662
  readAndResetSlackReplyBindingClassifications,
663
663
  readAndResetSlackReplyTargetClassifications
664
664
  };
665
- //# sourceMappingURL=responsiveness-probe-52IZOP2M.js.map
665
+ //# sourceMappingURL=responsiveness-probe-KW7KQJUY.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.28.522",
3
+ "version": "0.28.524",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {