chain-insights 0.24.2 → 0.25.0

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
@@ -22,7 +22,7 @@ as-is on macOS; on Windows use WSL.
22
22
  ```bash
23
23
  npx chain-insights@latest --help # run without installing
24
24
  npm install -g chain-insights # or install the cia CLI globally
25
- cia mcp call aml_address_risk network=robinhood address=0xYourAddressHere
25
+ cia aml-address-risk --address 0xYourAddressHere --network robinhood
26
26
  cia networks # network status + dataset overview
27
27
  cia network robinhood # details for one network
28
28
  ```
@@ -31,6 +31,20 @@ Sixty seconds gets you the CLI, a network overview, and the remote tool catalog.
31
31
  To call the same tools from an agent, register the MCP proxy:
32
32
  `cia setup claude-code` (or `codex` / `hermes`).
33
33
 
34
+ CLI results are human-readable by default. Add `--json` when another tool or
35
+ script needs indented JSON:
36
+
37
+ ```bash
38
+ cia mcp call --json graph_query \
39
+ network=robinhood \
40
+ "query=USE topology MATCH (a:Address) RETURN a.address AS address LIMIT 10"
41
+ cia aml-address-risk --json --address 0xYourAddressHere --network robinhood
42
+ ```
43
+
44
+ The AML address-risk contract uses the latest version when `version` is
45
+ omitted. Pin the current contract with `--version v1` on the AML command, or
46
+ with `version=v1` when using `cia mcp call aml_address_risk`.
47
+
34
48
  ## Purpose And Ownership
35
49
 
36
50
  One public npm package (`chain-insights`) providing the `cia` CLI and a
@@ -210,6 +224,13 @@ cia update --check
210
224
 
211
225
  Run a first screen from any directory:
212
226
 
227
+ ```bash
228
+ cia aml-address-risk \
229
+ --address 0xYourAddressHere --network robinhood
230
+ ```
231
+
232
+ The same screen is available through the generic MCP caller:
233
+
213
234
  ```bash
214
235
  cia mcp call aml_address_risk \
215
236
  network=robinhood address=0xYourAddressHere
package/dist/cli.cjs CHANGED
@@ -6,6 +6,85 @@ let node_url = require("node:url");
6
6
  let node_path = require("node:path");
7
7
  node_path = require_rolldown_runtime.__toESM(node_path, 1);
8
8
  //#region src/mcp/print-result.ts
9
+ function isRecord(value) {
10
+ return !!value && typeof value === "object" && !Array.isArray(value);
11
+ }
12
+ function displayValue(value) {
13
+ if (value === null || value === void 0) return "";
14
+ if (typeof value === "string") return value;
15
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
16
+ try {
17
+ return JSON.stringify(value);
18
+ } catch {
19
+ return String(value);
20
+ }
21
+ }
22
+ function formatTable(rows) {
23
+ if (rows.length === 0) return [];
24
+ const columns = [...new Set(rows.flatMap((row) => Object.keys(row)))];
25
+ const values = rows.map((row) => columns.map((column) => displayValue(row[column])));
26
+ const widths = columns.map((column, index) => Math.max(column.length, ...values.map((row) => row[index]?.length ?? 0)));
27
+ const line = (row) => row.map((value, index) => index === row.length - 1 ? value : value.padEnd(widths[index] ?? 0)).join(" | ");
28
+ return [
29
+ line(columns),
30
+ widths.map((width) => "-".repeat(width)).join("-+-"),
31
+ ...values.map(line)
32
+ ];
33
+ }
34
+ function formatGraphResult(value, fallbackTool) {
35
+ const facts = isRecord(value.facts) ? value.facts : void 0;
36
+ const query = facts && isRecord(facts.query) ? facts.query : void 0;
37
+ const queries = facts && Array.isArray(facts.queries) ? facts.queries : void 0;
38
+ if (!query && !queries) return null;
39
+ const lines = [`Tool: ${displayValue(value.tool) || fallbackTool || "MCP result"}`];
40
+ const subject = isRecord(value.subject) ? value.subject : facts && isRecord(facts.subject) ? facts.subject : void 0;
41
+ if (subject?.network !== void 0) lines.push(`Network: ${displayValue(subject.network)}`);
42
+ if (query) {
43
+ const results = Array.isArray(query.results) ? query.results.filter(isRecord) : [];
44
+ if (query.count !== void 0) lines.push(`Rows: ${displayValue(query.count)}`);
45
+ else lines.push(`Rows: ${results.length}`);
46
+ if (query.billable_units !== void 0) lines.push(`Billed units: ${displayValue(query.billable_units)}`);
47
+ if (query.elapsed_ms !== void 0) lines.push(`Elapsed: ${displayValue(query.elapsed_ms)} ms`);
48
+ if (query.truncated !== void 0) lines.push(`Truncated: ${displayValue(query.truncated)}`);
49
+ if (query.error !== void 0) lines.push(`Error: ${displayValue(query.error)}`);
50
+ if (results.length > 0) lines.push("", "Results:", ...formatTable(results));
51
+ else lines.push("", "Results: none");
52
+ }
53
+ if (queries) {
54
+ lines.push(`Queries: ${queries.length}`);
55
+ for (const entry of queries) {
56
+ if (!isRecord(entry)) continue;
57
+ const id = displayValue(entry.id) || "query";
58
+ const results = Array.isArray(entry.results) ? entry.results.filter(isRecord) : [];
59
+ lines.push("", `[${id}]`);
60
+ if (entry.error !== void 0) lines.push(`Error: ${displayValue(entry.error)}`);
61
+ lines.push(`Rows: ${displayValue(entry.count ?? results.length)}`);
62
+ if (results.length > 0) lines.push(...formatTable(results));
63
+ else lines.push("Results: none");
64
+ }
65
+ }
66
+ return lines.join("\n");
67
+ }
68
+ /**
69
+ * Formats one MCP text block for terminal output. JSON is indented when the
70
+ * caller requests `--json`; graph query envelopes are rendered as a compact
71
+ * result summary and table by default.
72
+ */
73
+ function formatMcpTextContent(text, tool, options = {}) {
74
+ let parsed;
75
+ try {
76
+ parsed = JSON.parse(text);
77
+ } catch {
78
+ return text;
79
+ }
80
+ if (options.json) try {
81
+ return JSON.stringify(parsed, null, 2);
82
+ } catch {
83
+ return text;
84
+ }
85
+ if (isRecord(parsed)) return formatGraphResult(parsed, tool) ?? JSON.stringify(parsed, null, 2);
86
+ return displayValue(parsed);
87
+ }
9
88
  /**
10
89
  * Prints the text blocks of an MCP tool result to stdout. When the result is
11
90
  * flagged `isError`, throws with the tool's error text instead — MCP `callTool`
@@ -13,10 +92,10 @@ node_path = require_rolldown_runtime.__toESM(node_path, 1);
13
92
  * surface them as failures (non-zero exit) rather than printing to stdout and
14
93
  * exiting 0.
15
94
  */
16
- function printMcpTextContent(result) {
95
+ function printMcpTextContent(result, options = {}) {
17
96
  const texts = (result.content ?? []).filter((item) => item.type === "text").map((item) => item.text ?? "");
18
97
  if (result.isError) throw new Error(texts.join("\n").trim() || "MCP tool returned an error");
19
- for (const text of texts) console.log(text);
98
+ for (const text of texts) console.log(formatMcpTextContent(text, options.tool, options));
20
99
  }
21
100
  //#endregion
22
101
  //#region src/cli.ts
@@ -29,6 +108,16 @@ function createCliCommand(name) {
29
108
  program.name("cia").description("AML investigation toolkit for blockchain analysis").version(require_version.PACKAGE_INFO.version).showHelpAfterError().option("--claude", "Install Claude Code skills globally to ~/.claude/skills/").option("--codex", "Install Codex skills globally to ~/.codex/skills/ and register MCP").option("--hermes", "Install Hermes skills globally to ~/.hermes/skills/chain-insights/ and register MCP");
30
109
  const rawArgs = process.argv.slice(2);
31
110
  const installerFlags = rawArgs.filter((a) => a === "--claude" || a === "--codex" || a === "--hermes");
111
+ function normalizeAmlToolVersionArgv(argv) {
112
+ const commandIndex = rawArgs.findIndex((arg, index) => arg === "aml-address-risk" && (index === 0 || index === 1 && rawArgs[0] === "mcp"));
113
+ if (commandIndex === -1) return argv;
114
+ return argv.map((arg, index) => {
115
+ if (index - 2 <= commandIndex) return arg;
116
+ if (arg === "--version") return "--tool-version";
117
+ if (arg.startsWith("--version=")) return `--tool-version=${arg.slice(10)}`;
118
+ return arg;
119
+ });
120
+ }
32
121
  const wantsHelpOrVersion = rawArgs.some((a) => a === "--help" || a === "-h" || a === "--version" || a === "-V");
33
122
  if (installerFlags.length > 0 && !wantsHelpOrVersion && !rawArgs.some((a) => !a.startsWith("-"))) {
34
123
  try {
@@ -100,16 +189,19 @@ async function printNetworkCapability(name, opts) {
100
189
  else console.log(formatNetworkCapability(network));
101
190
  }
102
191
  function addAmlAddressRiskCommand(parent, networksCommand) {
103
- parent.addCommand(createCliCommand("aml-address-risk").description("Screen an address for AML risk, exchange behavior, and optional comparison with another address").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", `Network to query. Run \`${networksCommand}\` for supported networks.`).option("--compare-address <address>", "Optional second address to compare against the screened address").action(async (opts) => {
192
+ parent.addCommand(createCliCommand("aml-address-risk").description("Screen an address for AML risk, exchange behavior, and optional comparison with another address").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", `Network to query. Run \`${networksCommand}\` for supported networks.`).option("--compare-address <address>", "Optional second address to compare against the screened address").option("--json", "Print machine-readable JSON output").option("--version <version>", "AML tool contract version. Omit to use the latest version (currently v1)").addOption(new commander.Option("--tool-version <version>", "Internal alias for the AML tool version").hideHelp()).action(async (opts) => {
104
193
  try {
194
+ const { resolveAmlAddressRiskVersion } = await Promise.resolve().then(() => require("./public-tools-DDGHRazh.cjs"));
195
+ const requestedVersion = opts.toolVersion ?? opts.version;
196
+ resolveAmlAddressRiskVersion(requestedVersion);
105
197
  await withGraphMcpClient("chain-insights-cli-aml-address-risk", async (client) => {
106
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-Bou25cki.cjs"));
107
- const result = await addressRisk(client, {
198
+ const { runAmlAddressRisk } = await Promise.resolve().then(() => require("./public-tools-DDGHRazh.cjs"));
199
+ const result = await runAmlAddressRisk(client, {
108
200
  address: opts.address,
109
201
  network: opts.network,
110
202
  compareAddress: opts.compareAddress
111
- });
112
- console.log(result.summaryText);
203
+ }, requestedVersion);
204
+ console.log(opts.json ? JSON.stringify(result.structuredContent, null, 2) : result.summaryText);
113
205
  });
114
206
  } catch (err) {
115
207
  console.error(err.message);
@@ -404,7 +496,7 @@ const mcpCommand = program.command("mcp").description("Interact with the Chain I
404
496
  try {
405
497
  const { loadSchema, saveSchema } = await Promise.resolve().then(() => require("./schema-cache-n7Gbhvsj.cjs"));
406
498
  const { formatToolsTable } = await Promise.resolve().then(() => require("./format-BjZuYDr8.cjs"));
407
- const { visibleRemoteTools } = await Promise.resolve().then(() => require("./tool-visibility-DA4pOuJt.cjs")).then((n) => n.tool_visibility_exports);
499
+ const { visibleRemoteTools } = await Promise.resolve().then(() => require("./tool-visibility-BBEbpKt4.cjs")).then((n) => n.tool_visibility_exports);
408
500
  const { loadConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
409
501
  const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Ypw9BNbn.cjs")).then((n) => n.client_exports);
410
502
  const config = await loadConfig();
@@ -433,20 +525,24 @@ const mcpCommand = program.command("mcp").description("Interact with the Chain I
433
525
  }
434
526
  }));
435
527
  addAmlAddressRiskCommand(mcpCommand, "cia mcp networks");
436
- mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool directly (debug)").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234... network=robinhood)").action(async (tool, rawArgs) => {
528
+ mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool directly (debug)").option("--json", "Print machine-readable JSON output").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234... network=robinhood)").action(async (tool, rawArgs, opts) => {
437
529
  try {
438
530
  const { parseMcpCallArgs } = await Promise.resolve().then(() => require("./call-args-DAiQSDmD.cjs"));
439
- const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await Promise.resolve().then(() => require("./tool-visibility-DA4pOuJt.cjs")).then((n) => n.tool_visibility_exports);
531
+ const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await Promise.resolve().then(() => require("./tool-visibility-BBEbpKt4.cjs")).then((n) => n.tool_visibility_exports);
440
532
  const args = parseMcpCallArgs(rawArgs);
441
533
  assertPublicMcpToolName(tool);
442
534
  validatePublicMcpToolArguments(tool, args);
535
+ if (tool === "aml_address_risk") {
536
+ const { resolveAmlAddressRiskVersion } = await Promise.resolve().then(() => require("./public-tools-DDGHRazh.cjs"));
537
+ resolveAmlAddressRiskVersion(args["version"] === void 0 ? void 0 : String(args["version"]));
538
+ }
443
539
  if (tool === "wallet_balance") {
444
540
  const { getWalletBalanceText } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
445
541
  console.log(await getWalletBalanceText());
446
542
  return;
447
543
  }
448
544
  if (tool === "meta_network_capabilities") {
449
- await printNetworkCapabilities({ json: true });
545
+ await printNetworkCapabilities({ json: opts.json });
450
546
  return;
451
547
  }
452
548
  if (tool === "meta_help") {
@@ -459,7 +555,10 @@ mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool dir
459
555
  printMcpTextContent(await client.callTool({
460
556
  name: "usage_status",
461
557
  arguments: {}
462
- }));
558
+ }), {
559
+ tool,
560
+ json: opts.json
561
+ });
463
562
  } catch (err) {
464
563
  const { isMissingUsageStatusToolError, primitiveBackendUsageStatus, usageStatusText } = await Promise.resolve().then(() => require("./usage-status-BdwwgYsu.cjs")).then((n) => n.usage_status_exports);
465
564
  if (!isMissingUsageStatusToolError(err)) throw err;
@@ -469,27 +568,30 @@ mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool dir
469
568
  return;
470
569
  }
471
570
  if (tool === "aml_address_risk") {
472
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-Bou25cki.cjs"));
473
- const result = await addressRisk(client, {
571
+ const { runAmlAddressRisk } = await Promise.resolve().then(() => require("./public-tools-DDGHRazh.cjs"));
572
+ const result = await runAmlAddressRisk(client, {
474
573
  address: String(args["address"] ?? ""),
475
574
  network: String(args["network"] ?? ""),
476
575
  compareAddress: args["compare_address"] === void 0 ? void 0 : String(args["compare_address"])
477
- });
478
- console.log(result.summaryText);
576
+ }, args["version"] === void 0 ? void 0 : String(args["version"]));
577
+ console.log(opts.json ? JSON.stringify(result.structuredContent, null, 2) : result.summaryText);
479
578
  return;
480
579
  }
481
580
  printMcpTextContent(await client.callTool({
482
581
  name: tool,
483
582
  arguments: args
484
- }));
583
+ }), {
584
+ tool,
585
+ json: opts.json
586
+ });
485
587
  });
486
588
  } catch (err) {
487
- const { formatMcpCallError } = await Promise.resolve().then(() => require("./tool-visibility-DA4pOuJt.cjs")).then((n) => n.tool_visibility_exports);
589
+ const { formatMcpCallError } = await Promise.resolve().then(() => require("./tool-visibility-BBEbpKt4.cjs")).then((n) => n.tool_visibility_exports);
488
590
  console.error(formatMcpCallError(tool, err));
489
591
  process.exit(1);
490
592
  }
491
593
  }));
492
- program.parseAsync(process.argv).catch((err) => {
594
+ program.parseAsync(normalizeAmlToolVersionArgv(process.argv)).catch((err) => {
493
595
  console.error(err.message);
494
596
  process.exit(1);
495
597
  });
package/dist/cli.mjs CHANGED
@@ -4,6 +4,85 @@ import { execFileSync } from "node:child_process";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import path from "node:path";
6
6
  //#region src/mcp/print-result.ts
7
+ function isRecord(value) {
8
+ return !!value && typeof value === "object" && !Array.isArray(value);
9
+ }
10
+ function displayValue(value) {
11
+ if (value === null || value === void 0) return "";
12
+ if (typeof value === "string") return value;
13
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
14
+ try {
15
+ return JSON.stringify(value);
16
+ } catch {
17
+ return String(value);
18
+ }
19
+ }
20
+ function formatTable(rows) {
21
+ if (rows.length === 0) return [];
22
+ const columns = [...new Set(rows.flatMap((row) => Object.keys(row)))];
23
+ const values = rows.map((row) => columns.map((column) => displayValue(row[column])));
24
+ const widths = columns.map((column, index) => Math.max(column.length, ...values.map((row) => row[index]?.length ?? 0)));
25
+ const line = (row) => row.map((value, index) => index === row.length - 1 ? value : value.padEnd(widths[index] ?? 0)).join(" | ");
26
+ return [
27
+ line(columns),
28
+ widths.map((width) => "-".repeat(width)).join("-+-"),
29
+ ...values.map(line)
30
+ ];
31
+ }
32
+ function formatGraphResult(value, fallbackTool) {
33
+ const facts = isRecord(value.facts) ? value.facts : void 0;
34
+ const query = facts && isRecord(facts.query) ? facts.query : void 0;
35
+ const queries = facts && Array.isArray(facts.queries) ? facts.queries : void 0;
36
+ if (!query && !queries) return null;
37
+ const lines = [`Tool: ${displayValue(value.tool) || fallbackTool || "MCP result"}`];
38
+ const subject = isRecord(value.subject) ? value.subject : facts && isRecord(facts.subject) ? facts.subject : void 0;
39
+ if (subject?.network !== void 0) lines.push(`Network: ${displayValue(subject.network)}`);
40
+ if (query) {
41
+ const results = Array.isArray(query.results) ? query.results.filter(isRecord) : [];
42
+ if (query.count !== void 0) lines.push(`Rows: ${displayValue(query.count)}`);
43
+ else lines.push(`Rows: ${results.length}`);
44
+ if (query.billable_units !== void 0) lines.push(`Billed units: ${displayValue(query.billable_units)}`);
45
+ if (query.elapsed_ms !== void 0) lines.push(`Elapsed: ${displayValue(query.elapsed_ms)} ms`);
46
+ if (query.truncated !== void 0) lines.push(`Truncated: ${displayValue(query.truncated)}`);
47
+ if (query.error !== void 0) lines.push(`Error: ${displayValue(query.error)}`);
48
+ if (results.length > 0) lines.push("", "Results:", ...formatTable(results));
49
+ else lines.push("", "Results: none");
50
+ }
51
+ if (queries) {
52
+ lines.push(`Queries: ${queries.length}`);
53
+ for (const entry of queries) {
54
+ if (!isRecord(entry)) continue;
55
+ const id = displayValue(entry.id) || "query";
56
+ const results = Array.isArray(entry.results) ? entry.results.filter(isRecord) : [];
57
+ lines.push("", `[${id}]`);
58
+ if (entry.error !== void 0) lines.push(`Error: ${displayValue(entry.error)}`);
59
+ lines.push(`Rows: ${displayValue(entry.count ?? results.length)}`);
60
+ if (results.length > 0) lines.push(...formatTable(results));
61
+ else lines.push("Results: none");
62
+ }
63
+ }
64
+ return lines.join("\n");
65
+ }
66
+ /**
67
+ * Formats one MCP text block for terminal output. JSON is indented when the
68
+ * caller requests `--json`; graph query envelopes are rendered as a compact
69
+ * result summary and table by default.
70
+ */
71
+ function formatMcpTextContent(text, tool, options = {}) {
72
+ let parsed;
73
+ try {
74
+ parsed = JSON.parse(text);
75
+ } catch {
76
+ return text;
77
+ }
78
+ if (options.json) try {
79
+ return JSON.stringify(parsed, null, 2);
80
+ } catch {
81
+ return text;
82
+ }
83
+ if (isRecord(parsed)) return formatGraphResult(parsed, tool) ?? JSON.stringify(parsed, null, 2);
84
+ return displayValue(parsed);
85
+ }
7
86
  /**
8
87
  * Prints the text blocks of an MCP tool result to stdout. When the result is
9
88
  * flagged `isError`, throws with the tool's error text instead — MCP `callTool`
@@ -11,10 +90,10 @@ import path from "node:path";
11
90
  * surface them as failures (non-zero exit) rather than printing to stdout and
12
91
  * exiting 0.
13
92
  */
14
- function printMcpTextContent(result) {
93
+ function printMcpTextContent(result, options = {}) {
15
94
  const texts = (result.content ?? []).filter((item) => item.type === "text").map((item) => item.text ?? "");
16
95
  if (result.isError) throw new Error(texts.join("\n").trim() || "MCP tool returned an error");
17
- for (const text of texts) console.log(text);
96
+ for (const text of texts) console.log(formatMcpTextContent(text, options.tool, options));
18
97
  }
19
98
  //#endregion
20
99
  //#region src/cli.ts
@@ -27,6 +106,16 @@ function createCliCommand(name) {
27
106
  program.name("cia").description("AML investigation toolkit for blockchain analysis").version(PACKAGE_INFO.version).showHelpAfterError().option("--claude", "Install Claude Code skills globally to ~/.claude/skills/").option("--codex", "Install Codex skills globally to ~/.codex/skills/ and register MCP").option("--hermes", "Install Hermes skills globally to ~/.hermes/skills/chain-insights/ and register MCP");
28
107
  const rawArgs = process.argv.slice(2);
29
108
  const installerFlags = rawArgs.filter((a) => a === "--claude" || a === "--codex" || a === "--hermes");
109
+ function normalizeAmlToolVersionArgv(argv) {
110
+ const commandIndex = rawArgs.findIndex((arg, index) => arg === "aml-address-risk" && (index === 0 || index === 1 && rawArgs[0] === "mcp"));
111
+ if (commandIndex === -1) return argv;
112
+ return argv.map((arg, index) => {
113
+ if (index - 2 <= commandIndex) return arg;
114
+ if (arg === "--version") return "--tool-version";
115
+ if (arg.startsWith("--version=")) return `--tool-version=${arg.slice(10)}`;
116
+ return arg;
117
+ });
118
+ }
30
119
  const wantsHelpOrVersion = rawArgs.some((a) => a === "--help" || a === "-h" || a === "--version" || a === "-V");
31
120
  if (installerFlags.length > 0 && !wantsHelpOrVersion && !rawArgs.some((a) => !a.startsWith("-"))) {
32
121
  try {
@@ -98,16 +187,19 @@ async function printNetworkCapability(name, opts) {
98
187
  else console.log(formatNetworkCapability(network));
99
188
  }
100
189
  function addAmlAddressRiskCommand(parent, networksCommand) {
101
- parent.addCommand(createCliCommand("aml-address-risk").description("Screen an address for AML risk, exchange behavior, and optional comparison with another address").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", `Network to query. Run \`${networksCommand}\` for supported networks.`).option("--compare-address <address>", "Optional second address to compare against the screened address").action(async (opts) => {
190
+ parent.addCommand(createCliCommand("aml-address-risk").description("Screen an address for AML risk, exchange behavior, and optional comparison with another address").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", `Network to query. Run \`${networksCommand}\` for supported networks.`).option("--compare-address <address>", "Optional second address to compare against the screened address").option("--json", "Print machine-readable JSON output").option("--version <version>", "AML tool contract version. Omit to use the latest version (currently v1)").addOption(new Option("--tool-version <version>", "Internal alias for the AML tool version").hideHelp()).action(async (opts) => {
102
191
  try {
192
+ const { resolveAmlAddressRiskVersion } = await import("./public-tools-CMI_0y87.mjs");
193
+ const requestedVersion = opts.toolVersion ?? opts.version;
194
+ resolveAmlAddressRiskVersion(requestedVersion);
103
195
  await withGraphMcpClient("chain-insights-cli-aml-address-risk", async (client) => {
104
- const { addressRisk } = await import("./public-tools-CpOLkME5.mjs");
105
- const result = await addressRisk(client, {
196
+ const { runAmlAddressRisk } = await import("./public-tools-CMI_0y87.mjs");
197
+ const result = await runAmlAddressRisk(client, {
106
198
  address: opts.address,
107
199
  network: opts.network,
108
200
  compareAddress: opts.compareAddress
109
- });
110
- console.log(result.summaryText);
201
+ }, requestedVersion);
202
+ console.log(opts.json ? JSON.stringify(result.structuredContent, null, 2) : result.summaryText);
111
203
  });
112
204
  } catch (err) {
113
205
  console.error(err.message);
@@ -402,7 +494,7 @@ const mcpCommand = program.command("mcp").description("Interact with the Chain I
402
494
  try {
403
495
  const { loadSchema, saveSchema } = await import("./schema-cache-DJdU4MIP.mjs");
404
496
  const { formatToolsTable } = await import("./format-DB2IH2U5.mjs");
405
- const { visibleRemoteTools } = await import("./tool-visibility-wDMzmHU-.mjs").then((n) => n.i);
497
+ const { visibleRemoteTools } = await import("./tool-visibility-CJqjmDF5.mjs").then((n) => n.i);
406
498
  const { loadConfig } = await import("./config-DbbPiGk0.mjs").then((n) => n.t);
407
499
  const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await import("./client-CHYskPnG.mjs").then((n) => n.r);
408
500
  const config = await loadConfig();
@@ -431,20 +523,24 @@ const mcpCommand = program.command("mcp").description("Interact with the Chain I
431
523
  }
432
524
  }));
433
525
  addAmlAddressRiskCommand(mcpCommand, "cia mcp networks");
434
- mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool directly (debug)").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234... network=robinhood)").action(async (tool, rawArgs) => {
526
+ mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool directly (debug)").option("--json", "Print machine-readable JSON output").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234... network=robinhood)").action(async (tool, rawArgs, opts) => {
435
527
  try {
436
528
  const { parseMcpCallArgs } = await import("./call-args-ysbB_xdA.mjs");
437
- const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await import("./tool-visibility-wDMzmHU-.mjs").then((n) => n.i);
529
+ const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await import("./tool-visibility-CJqjmDF5.mjs").then((n) => n.i);
438
530
  const args = parseMcpCallArgs(rawArgs);
439
531
  assertPublicMcpToolName(tool);
440
532
  validatePublicMcpToolArguments(tool, args);
533
+ if (tool === "aml_address_risk") {
534
+ const { resolveAmlAddressRiskVersion } = await import("./public-tools-CMI_0y87.mjs");
535
+ resolveAmlAddressRiskVersion(args["version"] === void 0 ? void 0 : String(args["version"]));
536
+ }
441
537
  if (tool === "wallet_balance") {
442
538
  const { getWalletBalanceText } = await import("./tools-BRQAPF2R.mjs").then((n) => n.p);
443
539
  console.log(await getWalletBalanceText());
444
540
  return;
445
541
  }
446
542
  if (tool === "meta_network_capabilities") {
447
- await printNetworkCapabilities({ json: true });
543
+ await printNetworkCapabilities({ json: opts.json });
448
544
  return;
449
545
  }
450
546
  if (tool === "meta_help") {
@@ -457,7 +553,10 @@ mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool dir
457
553
  printMcpTextContent(await client.callTool({
458
554
  name: "usage_status",
459
555
  arguments: {}
460
- }));
556
+ }), {
557
+ tool,
558
+ json: opts.json
559
+ });
461
560
  } catch (err) {
462
561
  const { isMissingUsageStatusToolError, primitiveBackendUsageStatus, usageStatusText } = await import("./usage-status-CHiOPA-2.mjs").then((n) => n.n);
463
562
  if (!isMissingUsageStatusToolError(err)) throw err;
@@ -467,27 +566,30 @@ mcpCommand.addCommand(createCliCommand("call").description("Call an MCP tool dir
467
566
  return;
468
567
  }
469
568
  if (tool === "aml_address_risk") {
470
- const { addressRisk } = await import("./public-tools-CpOLkME5.mjs");
471
- const result = await addressRisk(client, {
569
+ const { runAmlAddressRisk } = await import("./public-tools-CMI_0y87.mjs");
570
+ const result = await runAmlAddressRisk(client, {
472
571
  address: String(args["address"] ?? ""),
473
572
  network: String(args["network"] ?? ""),
474
573
  compareAddress: args["compare_address"] === void 0 ? void 0 : String(args["compare_address"])
475
- });
476
- console.log(result.summaryText);
574
+ }, args["version"] === void 0 ? void 0 : String(args["version"]));
575
+ console.log(opts.json ? JSON.stringify(result.structuredContent, null, 2) : result.summaryText);
477
576
  return;
478
577
  }
479
578
  printMcpTextContent(await client.callTool({
480
579
  name: tool,
481
580
  arguments: args
482
- }));
581
+ }), {
582
+ tool,
583
+ json: opts.json
584
+ });
483
585
  });
484
586
  } catch (err) {
485
- const { formatMcpCallError } = await import("./tool-visibility-wDMzmHU-.mjs").then((n) => n.i);
587
+ const { formatMcpCallError } = await import("./tool-visibility-CJqjmDF5.mjs").then((n) => n.i);
486
588
  console.error(formatMcpCallError(tool, err));
487
589
  process.exit(1);
488
590
  }
489
591
  }));
490
- program.parseAsync(process.argv).catch((err) => {
592
+ program.parseAsync(normalizeAmlToolVersionArgv(process.argv)).catch((err) => {
491
593
  console.error(err.message);
492
594
  process.exit(1);
493
595
  });