@iicp/client 0.7.82 → 0.7.84

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/README.md CHANGED
@@ -39,7 +39,7 @@ What good looks like:
39
39
  ```bash
40
40
  iicp-node --help # shows query, serve, proxy, mcp-gateway, credits, ...
41
41
  which iicp-node # points to your Node/npm environment
42
- iicp-node --version # prints iicp-node 0.7.82 or newer
42
+ iicp-node --version # prints iicp-node 0.7.84 or newer
43
43
  ```
44
44
 
45
45
  The query command contacts the public directory, discovers a matching live node,
@@ -51,6 +51,16 @@ keeps key-ready transport/relay paths confidential, but it is not
51
51
  executor-blind inference. For sensitive data, use local/browser inference or a
52
52
  fail-closed routing profile.
53
53
 
54
+ ## MCP gateway safety
55
+
56
+ `iicp-node mcp-gateway --tools format_json,summarize_text` advertises only the
57
+ tools you name. Shell, file, network, browser, credential, system-control and
58
+ regulated-decision tools are denied by default. Enabling one requires all four
59
+ controls: `--allow-dangerous-tools`, `--authz-policy ID`, `--sandbox container`
60
+ and `--audit-redaction` (equivalent `IICP_MCP_*` environment variables exist).
61
+ Policy receipts include risk/decision metadata and argument counts, never tool
62
+ arguments, prompts, credentials or response content.
63
+
54
64
  ## Use from TypeScript
55
65
 
56
66
  ```typescript
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAiDA,OAAO,EAeL,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAIvB,KAAK,aAAa,GAAG,cAAc,cAAc,CAAC,CAAC;AAEnD,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,yBAA8B,GAAG,MAAM,IAAI,CA+C3F;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,qGAAqG;IACrG,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iGAAiG;IACjG,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoBD,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC;AACtE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;AAE/D,wBAAgB,uBAAuB,IAAI,gBAAgB,CAM1D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,OAAO,GAAG,kBAAkB,CAGpG;AAED,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAKrF;AAsaD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,OAAO,GACrB,KAAK,CAAC,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC,CAGtC;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWlE;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAEhB,OAAO,CAAC,EAAE,GAAG,GACZ,MAAM,GAAG,IAAI,CAUf;AAiFD,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,GAAG,SAAS,CAsB9E;AA+2BD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA+D5D;AA0pBD,wBAAsB,IAAI,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBlF"}
package/dist/cli.js CHANGED
@@ -50,6 +50,7 @@ const index_js_2 = require("./backends/index.js");
50
50
  const recovery_js_1 = require("./recovery.js");
51
51
  const identity_js_1 = require("./identity.js");
52
52
  const delegation_js_1 = require("./delegation.js");
53
+ const mcp_policy_js_1 = require("./mcp_policy.js");
53
54
  /**
54
55
  * Start the default-on provider updater for long-running TS node processes.
55
56
  *
@@ -2152,20 +2153,6 @@ async function main(argv = process.argv.slice(2)) {
2152
2153
  }
2153
2154
  }
2154
2155
  // ── mcp-gateway (#512) ───────────────────────────────────────────────────────
2155
- // Backstop denylist on top of the operator's explicit --tools allowlist
2156
- // (red-team pass 3): shells/interpreters/exec primitives never to expose, even
2157
- // by accident. The required --tools allowlist + allow_tool_execution opt-in are
2158
- // the primary controls; this is a best-effort safety net.
2159
- const _MCP_DANGEROUS = new Set([
2160
- // shells / interpreters / process execution
2161
- "bash", "sh", "zsh", "fish", "shell", "powershell", "pwsh", "cmd",
2162
- "exec", "execute", "run_command", "run", "system", "eval",
2163
- "python", "python3", "node", "ruby", "perl", "subprocess", "popen", "spawn",
2164
- // #601 tool-risk classes that must not be public-unknown by default
2165
- "write_file", "file_write", "filesystem_write", "delete_file", "remove_file",
2166
- "browser_control", "computer_use", "credential_access", "read_secret", "secrets",
2167
- "system_control", "service_control", "physical_world", "regulated_decision",
2168
- ]);
2169
2156
  function _toolToIntent(name) {
2170
2157
  const safe = name.toLowerCase().replace(/[^a-z0-9_]/g, "_");
2171
2158
  return `urn:iicp:intent:mcp:${safe}:v1`;
@@ -2183,7 +2170,11 @@ async function runMcpGateway(argv) {
2183
2170
  ` --directory-url URL IICP_DIRECTORY_URL (default https://iicp.network/api/v1)\n` +
2184
2171
  ` --region REGION IICP_REGION (default local)\n` +
2185
2172
  ` --port N IICP_PORT (default 9484)\n` +
2186
- ` --host HOST IICP_HOST (default ::)\n`);
2173
+ ` --host HOST IICP_HOST (default ::)\n` +
2174
+ ` --allow-dangerous-tools IICP_MCP_ALLOW_DANGEROUS_TOOLS (requires all controls below)\n` +
2175
+ ` --authz-policy ID IICP_MCP_AUTHZ_POLICY\n` +
2176
+ ` --sandbox PROFILE IICP_MCP_SANDBOX (strict/container/sandbox)\n` +
2177
+ ` --audit-redaction IICP_MCP_AUDIT_REDACTION\n`);
2187
2178
  return 0;
2188
2179
  }
2189
2180
  const { values } = safeParseArgs({
@@ -2197,15 +2188,32 @@ async function runMcpGateway(argv) {
2197
2188
  region: { type: "string" },
2198
2189
  port: { type: "string" },
2199
2190
  host: { type: "string" },
2191
+ "allow-dangerous-tools": { type: "boolean" },
2192
+ "authz-policy": { type: "string" },
2193
+ sandbox: { type: "string" },
2194
+ "audit-redaction": { type: "boolean" },
2200
2195
  },
2201
2196
  allowPositionals: false,
2202
2197
  });
2203
2198
  const mcpUrl = (values["mcp-url"] ?? envOr("IICP_MCP_URL") ?? "http://localhost:8001").replace(/\/$/, "");
2204
2199
  const rawTools = (values["tools"] ?? envOr("IICP_MCP_TOOLS") ?? "")
2205
2200
  .split(",").map((t) => t.trim()).filter(Boolean);
2206
- const activeTools = rawTools.filter((t) => !_MCP_DANGEROUS.has(t.toLowerCase()));
2201
+ const toolPolicy = new mcp_policy_js_1.McpToolPolicy({
2202
+ allowDangerousTools: Boolean(values["allow-dangerous-tools"]) || envBool("IICP_MCP_ALLOW_DANGEROUS_TOOLS"),
2203
+ authzPolicy: values["authz-policy"] ?? envOr("IICP_MCP_AUTHZ_POLICY") ?? "",
2204
+ sandboxProfile: values["sandbox"] ?? envOr("IICP_MCP_SANDBOX") ?? "",
2205
+ auditRedaction: Boolean(values["audit-redaction"]) || envBool("IICP_MCP_AUDIT_REDACTION"),
2206
+ });
2207
+ const activeTools = rawTools.filter((t) => toolPolicy.allows(t));
2208
+ const deniedTools = rawTools.filter((t) => !toolPolicy.allows(t));
2209
+ if (deniedTools.length) {
2210
+ process.stderr.write(`WARNING: denied high-risk MCP tools until all authz, sandbox and redacted-audit controls are configured: ${deniedTools.join(", ")}\n`);
2211
+ }
2207
2212
  if (activeTools.length === 0) {
2208
- process.stderr.write(`ERROR: --tools is required. Provide a comma-separated list of MCP tool names.\n` +
2213
+ const reason = rawTools.length > 0
2214
+ ? "all requested tools were denied by the MCP safety policy"
2215
+ : "--tools is required";
2216
+ process.stderr.write(`ERROR: ${reason}. Provide safe tool names, or configure every dangerous-tool control.\n` +
2209
2217
  ` Example: iicp-node mcp-gateway --tools summarize_text,lookup_status --mcp-url http://localhost:8001\n`);
2210
2218
  return 2;
2211
2219
  }
@@ -2216,9 +2224,26 @@ async function runMcpGateway(argv) {
2216
2224
  const host = values["host"] ?? envOr("IICP_HOST") ?? "::";
2217
2225
  const publicEndpoint = values["public-endpoint"] ?? envOr("IICP_PUBLIC_ENDPOINT") ?? `http://localhost:${port}`;
2218
2226
  const intents = activeTools.map(_toolToIntent);
2227
+ const capabilities = activeTools.map((tool, index) => ({
2228
+ intent: intents[index],
2229
+ models: [`mcp:${tool}`],
2230
+ max_tokens: 65536,
2231
+ }));
2219
2232
  let nodeToken = envOr("IICP_NODE_TOKEN") ?? "";
2220
2233
  async function doRegister() {
2221
- const payload = { node_id: nodeId, region, endpoint: publicEndpoint, intents, mcp_tools: activeTools, protocol_version: "1.0" };
2234
+ const payload = {
2235
+ node_id: nodeId,
2236
+ region,
2237
+ endpoint: publicEndpoint,
2238
+ capabilities,
2239
+ limits: { max_concurrent: 1, tokens_per_min: 65536 },
2240
+ backend: "custom",
2241
+ policy: {
2242
+ allow_remote_inference: false,
2243
+ allow_tool_execution: true,
2244
+ allow_file_access: activeTools.some((tool) => ["file_read", "file_write"].includes((0, mcp_policy_js_1.toolRiskLabel)(tool))),
2245
+ },
2246
+ };
2222
2247
  const headers = { "Content-Type": "application/json" };
2223
2248
  if (nodeToken)
2224
2249
  headers["Authorization"] = `Bearer ${nodeToken}`;
@@ -2271,7 +2296,16 @@ async function runMcpGateway(argv) {
2271
2296
  const stopAutoUpdate = startProviderAutoUpdate();
2272
2297
  const server = http.createServer(async (req, res) => {
2273
2298
  if (req.method === "GET" && req.url === "/iicp/health") {
2274
- const body = JSON.stringify({ status: "ok", node_id: nodeId, active_tools: activeTools, mcp_server: mcpUrl, timestamp: Math.floor(Date.now() / 1000) });
2299
+ const body = JSON.stringify({
2300
+ status: "ok", node_id: nodeId, active_tools: activeTools, mcp_server: mcpUrl,
2301
+ mcp_policy: {
2302
+ dangerous_tools_enabled: toolPolicy.dangerousReady,
2303
+ authz_policy: toolPolicy.authzPolicy || null,
2304
+ sandbox_profile: toolPolicy.sandboxProfile || null,
2305
+ audit_redacted: toolPolicy.auditRedaction,
2306
+ },
2307
+ timestamp: Math.floor(Date.now() / 1000),
2308
+ });
2275
2309
  res.writeHead(200, { "Content-Type": "application/json" });
2276
2310
  res.end(body);
2277
2311
  return;
@@ -2307,9 +2341,11 @@ async function runMcpGateway(argv) {
2307
2341
  res.end(JSON.stringify({ error: "Cannot determine tool name" }));
2308
2342
  return;
2309
2343
  }
2310
- if (_MCP_DANGEROUS.has(toolName.toLowerCase())) {
2344
+ const args = (payload["arguments"] ?? {});
2345
+ const argumentCount = args && typeof args === "object" ? Object.keys(args).length : 0;
2346
+ if (!toolPolicy.allows(toolName)) {
2311
2347
  res.writeHead(403, { "Content-Type": "application/json" });
2312
- res.end(JSON.stringify({ error: "Tool not permitted" }));
2348
+ res.end(JSON.stringify({ error: "Tool not permitted by MCP risk policy", policy_receipt: toolPolicy.receipt(toolName, "denied", argumentCount) }));
2313
2349
  return;
2314
2350
  }
2315
2351
  if (activeTools.length && !activeTools.includes(toolName)) {
@@ -2319,9 +2355,9 @@ async function runMcpGateway(argv) {
2319
2355
  }
2320
2356
  const taskId = body["task_id"] ?? (0, node_crypto_1.randomUUID)();
2321
2357
  try {
2322
- const result = await callMcp(toolName, (payload["arguments"] ?? {}));
2358
+ const result = await callMcp(toolName, args);
2323
2359
  res.writeHead(200, { "Content-Type": "application/json" });
2324
- res.end(JSON.stringify({ task_id: taskId, status: "completed", result }));
2360
+ res.end(JSON.stringify({ task_id: taskId, status: "completed", result, policy_receipt: toolPolicy.receipt(toolName, "allowed", argumentCount) }));
2325
2361
  }
2326
2362
  catch (err) {
2327
2363
  const msg = err.message ?? "error";