chain-insights 0.24.1 → 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,19 +92,32 @@ 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
23
102
  const __dirname$1 = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
24
103
  const installerPath = node_path.default.resolve(__dirname$1, "..", "bin", "install.cjs");
25
104
  const program = new commander.Command();
26
- program.name("cia").description("AML investigation toolkit for blockchain analysis").version(require_version.PACKAGE_INFO.version).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");
105
+ function createCliCommand(name) {
106
+ return new commander.Command(name).showHelpAfterError();
107
+ }
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");
27
109
  const rawArgs = process.argv.slice(2);
28
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
+ }
29
121
  const wantsHelpOrVersion = rawArgs.some((a) => a === "--help" || a === "-h" || a === "--version" || a === "-V");
30
122
  if (installerFlags.length > 0 && !wantsHelpOrVersion && !rawArgs.some((a) => !a.startsWith("-"))) {
31
123
  try {
@@ -96,6 +188,27 @@ async function printNetworkCapability(name, opts) {
96
188
  if (opts.json) console.log(JSON.stringify(network, null, 2));
97
189
  else console.log(formatNetworkCapability(network));
98
190
  }
191
+ function addAmlAddressRiskCommand(parent, networksCommand) {
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) => {
193
+ try {
194
+ const { resolveAmlAddressRiskVersion } = await Promise.resolve().then(() => require("./public-tools-DDGHRazh.cjs"));
195
+ const requestedVersion = opts.toolVersion ?? opts.version;
196
+ resolveAmlAddressRiskVersion(requestedVersion);
197
+ await withGraphMcpClient("chain-insights-cli-aml-address-risk", async (client) => {
198
+ const { runAmlAddressRisk } = await Promise.resolve().then(() => require("./public-tools-DDGHRazh.cjs"));
199
+ const result = await runAmlAddressRisk(client, {
200
+ address: opts.address,
201
+ network: opts.network,
202
+ compareAddress: opts.compareAddress
203
+ }, requestedVersion);
204
+ console.log(opts.json ? JSON.stringify(result.structuredContent, null, 2) : result.summaryText);
205
+ });
206
+ } catch (err) {
207
+ console.error(err.message);
208
+ process.exit(1);
209
+ }
210
+ }));
211
+ }
99
212
  program.command("networks").description("Show supported network status and dataset overview").option("--json", "Print raw capability JSON").action(async (opts) => {
100
213
  try {
101
214
  await printNetworkOverview(opts);
@@ -145,7 +258,7 @@ program.command("update").description("Check npmjs for a newer Chain Insights re
145
258
  process.exit(1);
146
259
  }
147
260
  });
148
- program.command("debug").description("Configure Chain Insights Graph debug mode").addCommand(new commander.Command("on").description("Enable Chain Insights Graph debug mode without x402 payments").requiredOption("--token <token>", "Debug bearer token").option("--endpoint <url>", "Chain Insights Graph endpoint").action(async (opts) => {
261
+ program.command("debug").description("Configure Chain Insights Graph debug mode").addCommand(createCliCommand("on").description("Enable Chain Insights Graph debug mode without x402 payments").requiredOption("--token <token>", "Debug bearer token").option("--endpoint <url>", "Chain Insights Graph endpoint").action(async (opts) => {
149
262
  try {
150
263
  const { saveConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
151
264
  await saveConfig({
@@ -160,7 +273,7 @@ program.command("debug").description("Configure Chain Insights Graph debug mode"
160
273
  console.error(err.message);
161
274
  process.exit(1);
162
275
  }
163
- })).addCommand(new commander.Command("off").description("Disable Chain Insights Graph debug mode and use paid x402 calls").action(async () => {
276
+ })).addCommand(createCliCommand("off").description("Disable Chain Insights Graph debug mode and use paid x402 calls").action(async () => {
164
277
  try {
165
278
  const { saveConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
166
279
  await saveConfig({
@@ -173,7 +286,7 @@ program.command("debug").description("Configure Chain Insights Graph debug mode"
173
286
  console.error(err.message);
174
287
  process.exit(1);
175
288
  }
176
- })).addCommand(new commander.Command("status").description("Show Chain Insights Graph payment/debug mode").action(async () => {
289
+ })).addCommand(createCliCommand("status").description("Show Chain Insights Graph payment/debug mode").action(async () => {
177
290
  try {
178
291
  const { loadConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
179
292
  const config = await loadConfig();
@@ -186,7 +299,7 @@ program.command("debug").description("Configure Chain Insights Graph debug mode"
186
299
  process.exit(1);
187
300
  }
188
301
  }));
189
- program.command("access-key").description("Configure Chain Insights Graph test access key mode").addCommand(new commander.Command("set").description("Use a Chain Insights Graph test access key without x402 payments").argument("<key>", "Test access key").option("--endpoint <url>", "Chain Insights Graph endpoint").action(async (key, opts) => {
302
+ program.command("access-key").description("Configure Chain Insights Graph test access key mode").addCommand(createCliCommand("set").description("Use a Chain Insights Graph test access key without x402 payments").argument("<key>", "Test access key").option("--endpoint <url>", "Chain Insights Graph endpoint").action(async (key, opts) => {
190
303
  try {
191
304
  const normalizedKey = key.trim();
192
305
  if (!normalizedKey) throw new Error("Test access key is required");
@@ -203,7 +316,7 @@ program.command("access-key").description("Configure Chain Insights Graph test a
203
316
  console.error(err.message);
204
317
  process.exit(1);
205
318
  }
206
- })).addCommand(new commander.Command("clear").description("Remove the Chain Insights Graph test access key and use paid x402 calls").action(async () => {
319
+ })).addCommand(createCliCommand("clear").description("Remove the Chain Insights Graph test access key and use paid x402 calls").action(async () => {
207
320
  try {
208
321
  const { saveConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
209
322
  await saveConfig({
@@ -216,7 +329,7 @@ program.command("access-key").description("Configure Chain Insights Graph test a
216
329
  console.error(err.message);
217
330
  process.exit(1);
218
331
  }
219
- })).addCommand(new commander.Command("status").description("Show Chain Insights Graph test access key status").action(async () => {
332
+ })).addCommand(createCliCommand("status").description("Show Chain Insights Graph test access key status").action(async () => {
220
333
  try {
221
334
  const { loadConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
222
335
  const config = await loadConfig();
@@ -228,14 +341,14 @@ program.command("access-key").description("Configure Chain Insights Graph test a
228
341
  process.exit(1);
229
342
  }
230
343
  }));
231
- program.command("setup").description("Configure external MCP clients").addCommand(new commander.Command("claude-code").alias("claude").description("Install Claude Code skills and register the MCP proxy").action(() => {
344
+ program.command("setup").description("Configure external MCP clients").addCommand(createCliCommand("claude-code").alias("claude").description("Install Claude Code skills and register the MCP proxy").action(() => {
232
345
  runInstaller("--claude");
233
- })).addCommand(new commander.Command("codex").description("Install Codex skills and register the MCP proxy").action(() => {
346
+ })).addCommand(createCliCommand("codex").description("Install Codex skills and register the MCP proxy").action(() => {
234
347
  runInstaller("--codex");
235
- })).addCommand(new commander.Command("hermes").description("Install Hermes skills and register the MCP proxy").action(() => {
348
+ })).addCommand(createCliCommand("hermes").description("Install Hermes skills and register the MCP proxy").action(() => {
236
349
  runInstaller("--hermes");
237
350
  }));
238
- program.command("config").description("Read or write configuration values").addCommand(new commander.Command("get").argument("<key>", "Config key to read").action(async (key) => {
351
+ program.command("config").description("Read or write configuration values").addCommand(createCliCommand("get").description("Read one Chain Insights configuration value").argument("<key>", "Config key to read").action(async (key) => {
239
352
  const { loadConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
240
353
  const { CONFIG_KEYS } = await Promise.resolve().then(() => require("./schema-CtFWYoJz.cjs")).then((n) => n.schema_exports);
241
354
  if (!CONFIG_KEYS.includes(key)) {
@@ -244,7 +357,7 @@ program.command("config").description("Read or write configuration values").addC
244
357
  }
245
358
  const value = (await loadConfig())[key];
246
359
  console.log(value ?? "");
247
- })).addCommand(new commander.Command("set").argument("<key>", "Config key to write").argument("<value>", "Value to set").action(async (key, value) => {
360
+ })).addCommand(createCliCommand("set").description("Write one Chain Insights configuration value").argument("<key>", "Config key to write").argument("<value>", "Value to set").action(async (key, value) => {
248
361
  if (key === "walletPrivateKey") {
249
362
  try {
250
363
  const { setWalletPrivateKey } = await Promise.resolve().then(() => require("./wallet-B3hAr70M.cjs")).then((n) => n.wallet_exports);
@@ -271,7 +384,7 @@ program.command("config").description("Read or write configuration values").addC
271
384
  const displayed = key.toLowerCase().includes("token") ? "[redacted]" : coerced;
272
385
  console.log(`Set ${key} = ${displayed}`);
273
386
  }));
274
- program.command("wallet").description("Manage the local Base USDC payment wallet").addCommand(new commander.Command("create").description("Generate a new local Base payment wallet").action(async () => {
387
+ program.command("wallet").description("Manage the local Base USDC payment wallet").addCommand(createCliCommand("create").description("Generate a new local Base payment wallet").action(async () => {
275
388
  try {
276
389
  const { isWalletConfigured, setWalletPrivateKey, walletPath } = await Promise.resolve().then(() => require("./wallet-B3hAr70M.cjs")).then((n) => n.wallet_exports);
277
390
  const { createInterface } = await import("node:readline/promises");
@@ -300,7 +413,7 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
300
413
  console.error(err.message);
301
414
  process.exit(1);
302
415
  }
303
- })).addCommand(new commander.Command("import").description("Import a Base payment wallet").argument("<private-key>", "0x-prefixed EVM private key").option("--force", "Replace an existing wallet (the previous key is backed up next to wallet.json)").action(async (privateKey, opts) => {
416
+ })).addCommand(createCliCommand("import").description("Import a Base payment wallet").argument("<private-key>", "0x-prefixed EVM private key").option("--force", "Replace an existing wallet (the previous key is backed up next to wallet.json)").action(async (privateKey, opts) => {
304
417
  try {
305
418
  const { setWalletPrivateKey, isWalletConfigured } = await Promise.resolve().then(() => require("./wallet-B3hAr70M.cjs")).then((n) => n.wallet_exports);
306
419
  const replacing = opts.force === true && await isWalletConfigured();
@@ -314,7 +427,7 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
314
427
  console.error(err.message);
315
428
  process.exit(1);
316
429
  }
317
- })).addCommand(new commander.Command("address").description("Print the local payment wallet address").action(async () => {
430
+ })).addCommand(createCliCommand("address").description("Print the local payment wallet address").action(async () => {
318
431
  try {
319
432
  const { getWalletAccount } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
320
433
  const account = await getWalletAccount();
@@ -323,7 +436,7 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
323
436
  console.error(err.message);
324
437
  process.exit(1);
325
438
  }
326
- })).addCommand(new commander.Command("balance").description("Show the local payment wallet Base USDC balance").action(async () => {
439
+ })).addCommand(createCliCommand("balance").description("Show the local payment wallet Base USDC balance").action(async () => {
327
440
  try {
328
441
  const { getWalletBalanceText } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
329
442
  console.log(await getWalletBalanceText());
@@ -331,7 +444,7 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
331
444
  console.error(err.message);
332
445
  process.exit(1);
333
446
  }
334
- })).addCommand(new commander.Command("ready").description("Check and prepare the wallet for paid Chain Insights Graph calls").option("--check-only", "Only check readiness; do not submit the one-time payment setup").addOption(new commander.Option("--no-approve", "Deprecated alias for --check-only").hideHelp()).option("--payment-usdc <amount>", "USDC setup cap to prepare for paid calls", "1").addOption(new commander.Option("--approval-usdc <amount>", "Deprecated alias for --payment-usdc").hideHelp()).option("--json", "Print machine-readable readiness metadata").action(async (opts) => {
447
+ })).addCommand(createCliCommand("ready").description("Check and prepare the wallet for paid Chain Insights Graph calls").option("--check-only", "Only check readiness; do not submit the one-time payment setup").addOption(new commander.Option("--no-approve", "Deprecated alias for --check-only").hideHelp()).option("--payment-usdc <amount>", "USDC setup cap to prepare for paid calls", "1").addOption(new commander.Option("--approval-usdc <amount>", "Deprecated alias for --payment-usdc").hideHelp()).option("--json", "Print machine-readable readiness metadata").action(async (opts) => {
335
448
  try {
336
449
  const { formatWalletReadiness, parsePaymentApprovalUnits, prepareWalletForPaidCalls } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
337
450
  const result = await prepareWalletForPaidCalls({
@@ -347,7 +460,7 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
347
460
  console.error(err.message);
348
461
  process.exit(1);
349
462
  }
350
- })).addCommand(new commander.Command("topup").description("Open a local browser page to top up the payment wallet").option("--no-open", "Print the top-up URL without opening a browser").option("--json", "Print machine-readable top-up metadata").action(async (opts) => {
463
+ })).addCommand(createCliCommand("topup").description("Open a local browser page to top up the payment wallet").option("--no-open", "Print the top-up URL without opening a browser").option("--json", "Print machine-readable top-up metadata").action(async (opts) => {
351
464
  try {
352
465
  const { buildTopupInfo, getWalletAccount } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
353
466
  const { startTopupServer } = await Promise.resolve().then(() => require("./topup-server-YN3iHrHW.cjs")).then((n) => n.topup_server_exports);
@@ -371,18 +484,19 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
371
484
  process.exit(1);
372
485
  }
373
486
  }));
374
- program.command("mcp").description("Interact with the Chain Insights MCP endpoint").allowExcessArguments(false).addCommand(new commander.Command("networks").description("List the detailed Chain Insights capability matrix and tool support").option("--json", "Print raw capability JSON").action(async (opts) => {
487
+ addAmlAddressRiskCommand(program, "cia networks");
488
+ const mcpCommand = program.command("mcp").description("Interact with the Chain Insights MCP endpoint").allowExcessArguments(false).addCommand(createCliCommand("networks").description("List the detailed Chain Insights capability matrix and tool support").option("--json", "Print raw capability JSON").action(async (opts) => {
375
489
  try {
376
490
  await printNetworkCapabilities(opts);
377
491
  } catch (err) {
378
492
  console.error(err.message);
379
493
  process.exit(1);
380
494
  }
381
- })).addCommand(new commander.Command("tools").description("List remote GraphRAG MCP tools (cached for 24 hours)").option("--refresh", "Force refresh schema cache").action(async (opts) => {
495
+ })).addCommand(createCliCommand("tools").description("List remote GraphRAG MCP tools (cached for 24 hours)").option("--refresh", "Force refresh schema cache").action(async (opts) => {
382
496
  try {
383
497
  const { loadSchema, saveSchema } = await Promise.resolve().then(() => require("./schema-cache-n7Gbhvsj.cjs"));
384
498
  const { formatToolsTable } = await Promise.resolve().then(() => require("./format-BjZuYDr8.cjs"));
385
- const { visibleRemoteTools } = await Promise.resolve().then(() => require("./tool-visibility-C8F9Yoxy.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);
386
500
  const { loadConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
387
501
  const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Ypw9BNbn.cjs")).then((n) => n.client_exports);
388
502
  const config = await loadConfig();
@@ -409,35 +523,26 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
409
523
  console.error(err.message);
410
524
  process.exit(1);
411
525
  }
412
- })).addCommand(new commander.Command("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 `cia mcp networks` for supported networks.").option("--compare-address <address>", "Optional second address to compare against the screened address").action(async (opts) => {
413
- try {
414
- await withGraphMcpClient("chain-insights-cli-aml-address-risk", async (client) => {
415
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-Bou25cki.cjs"));
416
- const result = await addressRisk(client, {
417
- address: opts.address,
418
- network: opts.network,
419
- compareAddress: opts.compareAddress
420
- });
421
- console.log(result.summaryText);
422
- });
423
- } catch (err) {
424
- console.error(err.message);
425
- process.exit(1);
426
- }
427
- })).addCommand(new commander.Command("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
+ }));
527
+ addAmlAddressRiskCommand(mcpCommand, "cia mcp networks");
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) => {
428
529
  try {
429
530
  const { parseMcpCallArgs } = await Promise.resolve().then(() => require("./call-args-DAiQSDmD.cjs"));
430
- const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await Promise.resolve().then(() => require("./tool-visibility-C8F9Yoxy.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);
431
532
  const args = parseMcpCallArgs(rawArgs);
432
533
  assertPublicMcpToolName(tool);
433
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
+ }
434
539
  if (tool === "wallet_balance") {
435
540
  const { getWalletBalanceText } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
436
541
  console.log(await getWalletBalanceText());
437
542
  return;
438
543
  }
439
544
  if (tool === "meta_network_capabilities") {
440
- await printNetworkCapabilities({ json: true });
545
+ await printNetworkCapabilities({ json: opts.json });
441
546
  return;
442
547
  }
443
548
  if (tool === "meta_help") {
@@ -450,7 +555,10 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
450
555
  printMcpTextContent(await client.callTool({
451
556
  name: "usage_status",
452
557
  arguments: {}
453
- }));
558
+ }), {
559
+ tool,
560
+ json: opts.json
561
+ });
454
562
  } catch (err) {
455
563
  const { isMissingUsageStatusToolError, primitiveBackendUsageStatus, usageStatusText } = await Promise.resolve().then(() => require("./usage-status-BdwwgYsu.cjs")).then((n) => n.usage_status_exports);
456
564
  if (!isMissingUsageStatusToolError(err)) throw err;
@@ -460,26 +568,30 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
460
568
  return;
461
569
  }
462
570
  if (tool === "aml_address_risk") {
463
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-Bou25cki.cjs"));
464
- const result = await addressRisk(client, {
571
+ const { runAmlAddressRisk } = await Promise.resolve().then(() => require("./public-tools-DDGHRazh.cjs"));
572
+ const result = await runAmlAddressRisk(client, {
465
573
  address: String(args["address"] ?? ""),
466
574
  network: String(args["network"] ?? ""),
467
575
  compareAddress: args["compare_address"] === void 0 ? void 0 : String(args["compare_address"])
468
- });
469
- 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);
470
578
  return;
471
579
  }
472
580
  printMcpTextContent(await client.callTool({
473
581
  name: tool,
474
582
  arguments: args
475
- }));
583
+ }), {
584
+ tool,
585
+ json: opts.json
586
+ });
476
587
  });
477
588
  } catch (err) {
478
- console.error(err.message);
589
+ const { formatMcpCallError } = await Promise.resolve().then(() => require("./tool-visibility-BBEbpKt4.cjs")).then((n) => n.tool_visibility_exports);
590
+ console.error(formatMcpCallError(tool, err));
479
591
  process.exit(1);
480
592
  }
481
593
  }));
482
- program.parseAsync(process.argv).catch((err) => {
594
+ program.parseAsync(normalizeAmlToolVersionArgv(process.argv)).catch((err) => {
483
595
  console.error(err.message);
484
596
  process.exit(1);
485
597
  });