chain-insights 0.22.3 → 0.24.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.
Files changed (109) hide show
  1. package/README.md +33 -42
  2. package/bin/cli.js +1 -1
  3. package/bin/install.cjs +1 -1
  4. package/dist/{capabilities-BZI6qROg.mjs → capabilities-BPnw6nP_.mjs} +20 -2
  5. package/dist/{capabilities-BZI6qROg.mjs.map → capabilities-BPnw6nP_.mjs.map} +1 -1
  6. package/dist/{capabilities-CPcrxodx.cjs → capabilities-EMRzwPBU.cjs} +19 -1
  7. package/dist/cli.cjs +82 -92
  8. package/dist/cli.mjs +82 -92
  9. package/dist/cli.mjs.map +1 -1
  10. package/dist/{client-D4aM4bzP.mjs → client-CHYskPnG.mjs} +6 -6
  11. package/dist/client-CHYskPnG.mjs.map +1 -0
  12. package/dist/{client-CqAzD519.cjs → client-Ypw9BNbn.cjs} +5 -5
  13. package/dist/{config-DYiUgdzg.cjs → config-B542AM4w.cjs} +2 -3
  14. package/dist/{config-DiQs0rQX.mjs → config-DbbPiGk0.mjs} +2 -3
  15. package/dist/{config-DiQs0rQX.mjs.map → config-DbbPiGk0.mjs.map} +1 -1
  16. package/dist/create-C0buxEfU.mjs +48 -0
  17. package/dist/create-C0buxEfU.mjs.map +1 -0
  18. package/dist/create-DdggkF04.cjs +69 -0
  19. package/dist/html-generator-BCDtYcGs.mjs +16 -0
  20. package/dist/{html-generator-D2BDzLED.mjs.map → html-generator-BCDtYcGs.mjs.map} +1 -1
  21. package/dist/html-generator-DFwMRWN3.cjs +16 -0
  22. package/dist/index.cjs +9 -11
  23. package/dist/index.d.cts +10 -99
  24. package/dist/index.d.cts.map +1 -1
  25. package/dist/index.d.mts +10 -99
  26. package/dist/index.d.mts.map +1 -1
  27. package/dist/index.mjs +7 -9
  28. package/dist/mcp-proxy.cjs +40 -161
  29. package/dist/mcp-proxy.d.cts.map +1 -1
  30. package/dist/mcp-proxy.d.mts.map +1 -1
  31. package/dist/mcp-proxy.mjs +40 -161
  32. package/dist/mcp-proxy.mjs.map +1 -1
  33. package/dist/{public-tools-BFs_7U_Z.cjs → public-tools-Bou25cki.cjs} +153 -5
  34. package/dist/{public-tools-BjqZGGAC.mjs → public-tools-CpOLkME5.mjs} +152 -4
  35. package/dist/public-tools-CpOLkME5.mjs.map +1 -0
  36. package/dist/{schema-v5cwychf.mjs → schema-B0OuHW_l.mjs} +63 -4
  37. package/dist/schema-B0OuHW_l.mjs.map +1 -0
  38. package/dist/{schema-DepyuUEP.cjs → schema-CtFWYoJz.cjs} +72 -7
  39. package/dist/{tool-visibility-DZBAP62b.cjs → tool-visibility-C8F9Yoxy.cjs} +1 -2
  40. package/dist/{tool-visibility-C0ALejXI.mjs → tool-visibility-CXbwfKhv.mjs} +2 -3
  41. package/dist/tool-visibility-CXbwfKhv.mjs.map +1 -0
  42. package/dist/{tools-lPY6k-vJ.cjs → tools-BHfphgy9.cjs} +4 -4
  43. package/dist/{tools-BKLnlBG1.mjs → tools-BRQAPF2R.mjs} +5 -5
  44. package/dist/tools-BRQAPF2R.mjs.map +1 -0
  45. package/dist/{topup-server-rqI7bqem.mjs → topup-server-BLdF1SFQ.mjs} +2 -2
  46. package/dist/topup-server-BLdF1SFQ.mjs.map +1 -0
  47. package/dist/{topup-server-DAqmAuu1.cjs → topup-server-YN3iHrHW.cjs} +1 -1
  48. package/dist/{update-CJUfGCxs.mjs → update-MsoEFbhn.mjs} +2 -36
  49. package/dist/{update-CJUfGCxs.mjs.map → update-MsoEFbhn.mjs.map} +1 -1
  50. package/dist/{update-BJoXYucO.cjs → update-RKd0UW90.cjs} +0 -35
  51. package/dist/{wallet-BEvHrHi3.cjs → wallet-B3hAr70M.cjs} +3 -3
  52. package/dist/{wallet-fMbhvKXT.mjs → wallet-COcm4oIb.mjs} +4 -4
  53. package/dist/wallet-COcm4oIb.mjs.map +1 -0
  54. package/docs/architecture.md +18 -49
  55. package/docs/contributing.md +0 -3
  56. package/docs/development.md +3 -5
  57. package/docs/graph-tools.md +7 -32
  58. package/docs/mcp-proxy.md +32 -47
  59. package/docs/stability.md +0 -12
  60. package/package.json +3 -4
  61. package/skills/chain-insights-address-risk/SKILL.md +0 -1
  62. package/dist/app-BHRl5oDo.cjs +0 -145
  63. package/dist/app-BeZyCVuz.mjs +0 -140
  64. package/dist/app-BeZyCVuz.mjs.map +0 -1
  65. package/dist/artifact-server-B8WKXtXr.cjs +0 -47
  66. package/dist/artifact-server-C1fETWsc.mjs +0 -49
  67. package/dist/artifact-server-C1fETWsc.mjs.map +0 -1
  68. package/dist/client-D4aM4bzP.mjs.map +0 -1
  69. package/dist/graph-normalizer-B2Q2lgVy.cjs +0 -130
  70. package/dist/graph-normalizer-BA3Rbd6l.mjs +0 -127
  71. package/dist/graph-normalizer-BA3Rbd6l.mjs.map +0 -1
  72. package/dist/graph-reports-B6yoYbPq.mjs +0 -63
  73. package/dist/graph-reports-B6yoYbPq.mjs.map +0 -1
  74. package/dist/graph-reports-_gqzxvvs.cjs +0 -64
  75. package/dist/html-generator-B9f_GIi2.cjs +0 -86
  76. package/dist/html-generator-D2BDzLED.mjs +0 -70
  77. package/dist/init-C3AVZHFb.cjs +0 -319
  78. package/dist/init-CO-PRYhT.mjs +0 -319
  79. package/dist/init-CO-PRYhT.mjs.map +0 -1
  80. package/dist/limits-D3Mn-gig.mjs +0 -94
  81. package/dist/limits-D3Mn-gig.mjs.map +0 -1
  82. package/dist/limits-km3pmmL3.cjs +0 -115
  83. package/dist/mcp-endpoint-Bd3SvCkg.mjs +0 -41
  84. package/dist/mcp-endpoint-Bd3SvCkg.mjs.map +0 -1
  85. package/dist/mcp-endpoint-DdIVQKW5.cjs +0 -56
  86. package/dist/output-root-BK4pdjyz.mjs +0 -36
  87. package/dist/output-root-BK4pdjyz.mjs.map +0 -1
  88. package/dist/output-root-BewoQaTx.cjs +0 -46
  89. package/dist/public-tools-BjqZGGAC.mjs.map +0 -1
  90. package/dist/resolve-port-CbaEoODz.cjs +0 -18
  91. package/dist/resolve-port-DxPK7Ipx.mjs +0 -20
  92. package/dist/resolve-port-DxPK7Ipx.mjs.map +0 -1
  93. package/dist/schema-v5cwychf.mjs.map +0 -1
  94. package/dist/server-BDmHAF1w.mjs +0 -46
  95. package/dist/server-BDmHAF1w.mjs.map +0 -1
  96. package/dist/server-BjprY9Ef.cjs +0 -55
  97. package/dist/templates/graph.html +0 -1450
  98. package/dist/tool-visibility-C0ALejXI.mjs.map +0 -1
  99. package/dist/tools-BKLnlBG1.mjs.map +0 -1
  100. package/dist/topup-server-rqI7bqem.mjs.map +0 -1
  101. package/dist/viz-BJ_kyRjI.cjs +0 -217
  102. package/dist/viz-Uh_EF-qB.mjs +0 -206
  103. package/dist/viz-Uh_EF-qB.mjs.map +0 -1
  104. package/dist/wallet-fMbhvKXT.mjs.map +0 -1
  105. package/docs/images/graph-mcp-iframe.png +0 -0
  106. package/docs/images/graph-visualization.png +0 -0
  107. package/docs/images/quickstart-demo.svg +0 -1
  108. package/docs/investigation-workspaces.md +0 -108
  109. package/docs/search-limits.md +0 -73
package/README.md CHANGED
@@ -10,8 +10,8 @@
10
10
  Chain Insights is open-source AML and forensics infrastructure for AI agents
11
11
  and analysts: a hosted Chain Insights Graph you reach over MCP, screened
12
12
  through one CLI. It screens blockchain addresses for risk, explores fund flows
13
- through read-only graph queries, and renders graph reports from your own
14
- investigation folders. Every new account gets a free tier — a daily allowance
13
+ through read-only graph queries, and returns structured investigation facts.
14
+ Every new account gets a free tier — a daily allowance
15
15
  of graph queries, no payment setup — so you can run a first screen in minutes.
16
16
 
17
17
  ## Quickstart
@@ -22,14 +22,12 @@ 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 init ~/cases # optional local investigation folder
26
25
  cia mcp call aml_address_risk network=robinhood address=0xYourAddressHere
27
- cia networks # supported networks + public tool surface
26
+ cia networks # all supported networks
27
+ cia network robinhood # details for one network
28
28
  ```
29
29
 
30
- ![Terminal demo: help, workspace init, and the network tool surface in under a minute](docs/images/quickstart-demo.svg)
31
-
32
- Sixty seconds gets you the CLI, a workspace, and the live tool catalog.
30
+ Sixty seconds gets you the CLI and the live tool catalog.
33
31
  To call the same tools from an agent, register the MCP proxy:
34
32
  `cia setup claude-code` (or `codex` / `hermes`).
35
33
 
@@ -49,7 +47,6 @@ Owns:
49
47
  - The canonical public tool surface: prefixed `aml_*` / `graph_*` / `meta_*`
50
48
  / `wallet_*` tools.
51
49
  - Local wallet and payment on Base mainnet (payment chain only).
52
- - Investigation workspaces, graph reports, and visualization.
53
50
  - Shipped product skills under `skills/` (`chain-insights-*`), packaged
54
51
  into the npm tarball.
55
52
 
@@ -60,8 +57,8 @@ Never touches:
60
57
  - Automatic risk labeling. Address labels are served by the Chain Insights
61
58
  Graph backend and read through `aml_address_risk`; the CLI never writes
62
59
  labels.
63
- - Custodial wallets or hosted case databases. Investigation data stays in
64
- the local workspace unless the operator exports it.
60
+ - Custodial wallets or hosted case databases. Investigation data stays with
61
+ the caller.
65
62
 
66
63
  ### What You Can Do Today
67
64
 
@@ -93,13 +90,13 @@ Downstream:
93
90
  ## Architecture
94
91
 
95
92
  Chain Insights is the investigation layer above the Chain Insights Graph.
96
- The CLI and MCP proxy call graph tools over one MCP endpoint, keep all
97
- evidence in local workspace folders, and never write to the graph.
93
+ The CLI and MCP proxy call graph tools over one MCP endpoint and never write
94
+ to the graph.
98
95
 
99
96
  ```text
100
97
  Agent or CLI user
101
98
  -> Chain Insights CLI / MCP proxy
102
- -> local config, wallet, workspace, artifacts, reports
99
+ -> local config and wallet
103
100
  -> Chain Insights Graph
104
101
  -> graph intelligence for AML workflows
105
102
  ```
@@ -112,8 +109,6 @@ Source modules (hand-maintained):
112
109
  | `federation` | `src/federation` | [components/federation.md](docs/architecture/components/federation.md) |
113
110
  | `investigation` | `src/investigation` | [components/investigation.md](docs/architecture/components/investigation.md) |
114
111
  | `mcp` | `src/mcp` | [components/mcp.md](docs/architecture/components/mcp.md) |
115
- | `server` | `src/server` | [components/server.md](docs/architecture/components/server.md) |
116
- | `viz` | `src/viz` | [components/viz.md](docs/architecture/components/viz.md) |
117
112
  | `wallet` | `src/wallet` | [components/wallet.md](docs/architecture/components/wallet.md) |
118
113
 
119
114
  Entry points:
@@ -213,23 +208,24 @@ cia --version
213
208
  cia update --check
214
209
  ```
215
210
 
216
- Create an investigation workspace and run a first screen:
211
+ Run a first screen from any directory:
217
212
 
218
213
  ```bash
219
- mkdir -p ./chain-insights-investigations
220
- cd ./chain-insights-investigations
221
- cia init .
222
-
223
214
  cia mcp call aml_address_risk \
224
215
  network=robinhood address=0xYourAddressHere
216
+ ```
225
217
 
226
- find reports -maxdepth 3 -type f | sort
218
+ Create a local payment wallet when paid access is needed:
219
+
220
+ ```bash
221
+ cia wallet create
227
222
  ```
228
223
 
229
- Workspaces are plain local folders. Reports, graph JSON, graph HTML, and
230
- published bundles live under the initialized workspace. Export only when
231
- you need to share, hand off, or archive a review checkpoint — the handoff
232
- package lands under `published/<workspace-slug>/`.
224
+ The command shows the private key once in a clearly marked warning panel.
225
+ Save it in a secure password manager or offline backup, then type `BACKED UP`
226
+ to finish. The encrypted local copy is stored at
227
+ `~/.chain-insights/wallet.json`. Continue with `cia wallet ready` when you are
228
+ ready to enable paid access.
233
229
 
234
230
  Example queries. Direct topology:
235
231
 
@@ -299,9 +295,6 @@ The hosted graph includes a small public free tier for `graph_query`
299
295
  users receive the free tier first, then paid access continues
300
296
  automatically.
301
297
 
302
- Search bounds (hops, row limits, frontiers) are tunable per call, per
303
- network, or globally — see [Search limits](docs/search-limits.md).
304
-
305
298
  ## Test
306
299
 
307
300
  Local gate, in order:
@@ -349,25 +342,23 @@ cia --version && cia update --check
349
342
  ```
350
343
 
351
344
  If network or tool discovery fails, check the endpoint and access mode
352
- first. The CLI can still initialize workspaces and continue local
353
- investigation workflow without a reachable endpoint.
345
+ first. Confirm the endpoint with `cia config get graphMcpEndpoint` and retry
346
+ the command.
354
347
 
355
348
  ## Documentation Links
356
349
 
357
350
  Product docs:
358
351
 
359
- | Doc | Use it for |
360
- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
361
- | [Graph tools](docs/graph-tools.md) | Graph layers, `graph_query`, `graph_query_batch`, AML tool contracts, graph reports |
362
- | [Graph query compatibility](docs/graph-query-compatibility.md) | GQL/Cypher support per layer, rewrite recipes, traversal guidance |
363
- | [Search limits](docs/search-limits.md) | Tunable search/row/frontier/hop bounds, precedence, ceilings |
364
- | [Investigation workspaces](docs/investigation-workspaces.md) | `cia init`, workspace layout, artifacts, templates, reports, visualization |
365
- | [MCP proxy](docs/mcp-proxy.md) | Stdio proxy behavior, endpoint configuration, agent installers, auth modes |
366
- | [Architecture overview](docs/architecture.md) | Product layers, data flow, local storage, security model, config keys |
367
- | [Development](docs/development.md) | Build, test, and local install commands |
368
- | [Contributing](docs/contributing.md) | Development workflow, pull requests, release expectations |
369
- | [Stability policy](docs/stability.md) | Guaranteed surfaces (exit codes, MCP tool names, workspace layout), deprecation rules |
370
- | [Debugging](docs/debugging.md) | Local troubleshooting, diagnostics, debug workflows |
352
+ | Doc | Use it for |
353
+ | -------------------------------------------------------------- | -------------------------------------------------------------------------- |
354
+ | [Graph tools](docs/graph-tools.md) | Graph layers, `graph_query`, `graph_query_batch`, and AML tool contracts |
355
+ | [Graph query compatibility](docs/graph-query-compatibility.md) | GQL/Cypher support per layer, rewrite recipes, traversal guidance |
356
+ | [MCP proxy](docs/mcp-proxy.md) | Stdio proxy behavior, endpoint configuration, agent installers, auth modes |
357
+ | [Architecture overview](docs/architecture.md) | Product layers, data flow, security model, and config keys |
358
+ | [Development](docs/development.md) | Build, test, and local install commands |
359
+ | [Contributing](docs/contributing.md) | Development workflow, pull requests, release expectations |
360
+ | [Stability policy](docs/stability.md) | Guaranteed surfaces, deprecation rules, and compatibility expectations |
361
+ | [Debugging](docs/debugging.md) | Local troubleshooting, diagnostics, debug workflows |
371
362
 
372
363
  Architecture depth:
373
364
 
package/bin/cli.js CHANGED
@@ -4,6 +4,6 @@
4
4
  // CJS shim: bridges the npm bin entry to the ESM dist built by tsdown.
5
5
  // Dynamic import() is the correct bridge pattern from CommonJS to ESM.
6
6
  import('../dist/cli.mjs').catch((err) => {
7
- console.error('Failed to load chain-insights:', err.message)
7
+ console.error('Failed to load cia:', err.message)
8
8
  process.exit(1)
9
9
  })
package/bin/install.cjs CHANGED
@@ -282,5 +282,5 @@ for (const target of skillsTargets) {
282
282
  console.log(` ${cyan}Config:${reset} ${configPath}`)
283
283
  console.log(` ${cyan}Data dir:${reset} ${dataDir}`)
284
284
  console.log(
285
- `\n${dim}Run ${reset}${cyan}chain-insights status${reset}${dim} to verify the installation.${reset}\n`
285
+ `\n${dim}Run ${reset}${cyan}cia status${reset}${dim} to verify the installation.${reset}\n`
286
286
  )
@@ -1,10 +1,12 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { a as resolveGraphMcpEndpoint, n as applyMcpAuthHeaders } from "./client-D4aM4bzP.mjs";
2
+ import { a as resolveGraphMcpEndpoint, n as applyMcpAuthHeaders } from "./client-CHYskPnG.mjs";
3
3
  //#region src/mcp/capabilities.ts
4
4
  var capabilities_exports = /* @__PURE__ */ __exportAll({
5
5
  PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS: () => PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS,
6
6
  fetchNetworkCapabilities: () => fetchNetworkCapabilities,
7
+ findNetworkCapability: () => findNetworkCapability,
7
8
  formatNetworkCapabilities: () => formatNetworkCapabilities,
9
+ formatNetworkCapability: () => formatNetworkCapability,
8
10
  mirrorGraphNetworkCapabilities: () => mirrorGraphNetworkCapabilities
9
11
  });
10
12
  const PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS = {
@@ -123,7 +125,23 @@ function formatNetworkCapabilities(document) {
123
125
  ...networkRows
124
126
  ].join("\n");
125
127
  }
128
+ function findNetworkCapability(document, name) {
129
+ const normalizedName = name.trim().toLowerCase();
130
+ if (!normalizedName) return void 0;
131
+ return document.networks.find((network) => [network.network, network.display_name].some((candidate) => candidate?.trim().toLowerCase() === normalizedName));
132
+ }
133
+ function formatNetworkCapability(network) {
134
+ const rows = [
135
+ ["Network", network.display_name || network.network],
136
+ ["Identifier", network.network],
137
+ ["Status", network.default ? `${network.status} (default)` : network.status],
138
+ ["Dataset", datasetLabel(network)],
139
+ ["Available tools", availableTools(network).join(", ") || "none"]
140
+ ];
141
+ const labelWidth = Math.max(...rows.map(([label]) => label.length));
142
+ return rows.map(([label, value]) => `${label.padEnd(labelWidth)} ${value}`).join("\n");
143
+ }
126
144
  //#endregion
127
145
  export { mirrorGraphNetworkCapabilities as n, capabilities_exports as t };
128
146
 
129
- //# sourceMappingURL=capabilities-BZI6qROg.mjs.map
147
+ //# sourceMappingURL=capabilities-BPnw6nP_.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities-BZI6qROg.mjs","names":[],"sources":["../src/mcp/capabilities.ts"],"sourcesContent":["import type { InvestigatorConfig } from '../config/schema.js'\nimport { applyMcpAuthHeaders, resolveGraphMcpEndpoint } from './client.js'\n\nexport interface NetworkTopologyLayer {\n enabled: boolean\n coverage?: {\n from_block?: number\n to_block?: number\n from_timestamp?: string\n to_timestamp?: string\n chain_tip_block?: number\n blocks_behind_tip?: number\n }\n}\n\nexport interface NetworkLayerCapability {\n enabled: boolean\n live?: NetworkTopologyLayer\n archive?: NetworkTopologyLayer\n}\n\nexport interface NetworkCapability {\n network: string\n display_name?: string\n status: string\n default?: boolean\n layers: Record<string, NetworkLayerCapability>\n tools: Record<string, string>\n coverage?: {\n from_block?: number\n to_block?: number\n from_timestamp?: string\n to_timestamp?: string\n chain_tip_block?: number\n blocks_behind_tip?: number\n }\n freshness?: {\n last_processed_at?: string\n last_successful_sync_at?: string\n max_data_age_seconds?: number\n last_processing_duration_seconds?: number\n }\n}\n\nexport interface NetworkCapabilitiesDocument {\n schema: 'chain-insights.network-capabilities.v1'\n networks: NetworkCapability[]\n}\n\nexport const PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS = {\n aml_address_risk: 'available',\n graph_query: 'available',\n graph_query_batch: 'available',\n meta_network_capabilities: 'available',\n meta_usage_status: 'available',\n meta_help: 'available',\n wallet_balance: 'available',\n} as const\nconst AVAILABLE_TOOLS_PER_LINE = 3\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction advertisedNetwork(raw: unknown): NetworkCapability | null {\n if (!isRecord(raw) || typeof raw.network !== 'string' || raw.network.trim() === '') {\n return null\n }\n const network = raw.network.trim()\n const capability: NetworkCapability = {\n network,\n display_name:\n typeof raw.display_name === 'string' && raw.display_name.trim() !== ''\n ? raw.display_name\n : network,\n status: typeof raw.status === 'string' && raw.status.trim() !== '' ? raw.status : 'live',\n layers: {},\n tools: { ...PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS },\n }\n if (raw.default === true) capability.default = true\n if (raw.default === false) capability.default = false\n if (isRecord(raw.coverage)) capability.coverage = raw.coverage as NetworkCapability['coverage']\n if (isRecord(raw.freshness))\n capability.freshness = raw.freshness as NetworkCapability['freshness']\n return capability\n}\n\n/** Repeat GraphRAG's network list. CIA does not add, drop, or invent names. */\nexport function mirrorGraphNetworkCapabilities(document: {\n networks: unknown[]\n}): NetworkCapabilitiesDocument {\n return {\n schema: 'chain-insights.network-capabilities.v1',\n networks: document.networks\n .map((network) => advertisedNetwork(network))\n .filter((network): network is NetworkCapability => network !== null),\n }\n}\n\nfunction publicNetworkCapabilities(\n document: NetworkCapabilitiesDocument\n): NetworkCapabilitiesDocument {\n return mirrorGraphNetworkCapabilities(document)\n}\n\nfunction metadataNetworksUrl(endpoint: string): URL {\n const url = new URL(endpoint)\n url.pathname = '/metadata/networks'\n url.search = ''\n url.hash = ''\n return url\n}\n\nexport async function fetchNetworkCapabilities(\n config: Pick<InvestigatorConfig, 'graphMcpAuthToken' | 'graphMcpMode' | 'graphMcpEndpoint'>\n): Promise<NetworkCapabilitiesDocument> {\n const endpoint = resolveGraphMcpEndpoint(config)\n const request = metadataNetworksUrl(endpoint)\n const headers = new Headers()\n const token = config.graphMcpAuthToken?.trim()\n if (token) {\n applyMcpAuthHeaders(headers, token)\n }\n let response: Response\n try {\n response = await fetch(request, { headers })\n } catch (err) {\n throw new Error(`network capabilities unavailable at ${request}: ${(err as Error).message}`)\n }\n if (!response.ok) {\n throw new Error(`network capabilities unavailable at ${request}: HTTP ${response.status}`)\n }\n const parsed = (await response.json()) as NetworkCapabilitiesDocument\n if (\n parsed.schema !== 'chain-insights.network-capabilities.v1' ||\n !Array.isArray(parsed.networks)\n ) {\n throw new Error('network capabilities response has unsupported schema')\n }\n return publicNetworkCapabilities(parsed)\n}\n\nfunction availableTools(network: NetworkCapability): string[] {\n const effectiveTools = {\n ...(network.tools ?? {}),\n ...PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS,\n }\n const tools = Object.entries(effectiveTools)\n .filter(([, status]) => status === 'available')\n .map(([name]) => name)\n return tools.sort()\n}\n\nfunction availableToolLines(network: NetworkCapability): string[] {\n const tools = availableTools(network)\n if (tools.length === 0) return ['none']\n const lines: string[] = []\n for (let index = 0; index < tools.length; index += AVAILABLE_TOOLS_PER_LINE) {\n lines.push(tools.slice(index, index + AVAILABLE_TOOLS_PER_LINE).join(', '))\n }\n return lines\n}\n\nfunction shortDate(value?: string): string {\n if (!value) return ''\n return value.slice(0, 10)\n}\n\nfunction datasetLabel(network: NetworkCapability): string {\n const coverage = network.coverage\n if (!coverage) return 'unknown'\n const blockRange =\n coverage.from_block !== undefined && coverage.to_block !== undefined\n ? `${coverage.from_block}..${coverage.to_block}`\n : 'blocks unknown'\n const dateRange =\n coverage.from_timestamp && coverage.to_timestamp\n ? `${shortDate(coverage.from_timestamp)}..${shortDate(coverage.to_timestamp)}`\n : ''\n if (blockRange === 'blocks unknown' && dateRange === '') return 'unknown'\n if (blockRange === 'blocks unknown') return dateRange\n if (dateRange === '') return blockRange\n return `${blockRange} / ${dateRange}`\n}\n\nexport function formatNetworkCapabilities(document: NetworkCapabilitiesDocument): string {\n if (document.networks.length === 0) return 'No supported networks advertised.'\n const headers = ['Network', 'Dataset', 'Available tools']\n const widths = [14, 38, 64]\n const row = (values: string[]) =>\n values.map((value, index) => value.padEnd(widths[index]!)).join(' ')\n const networkRows = document.networks.flatMap((network) => {\n const toolLines = availableToolLines(network)\n return toolLines.map((toolLine, index) =>\n row([\n index === 0 ? network.display_name || network.network : '',\n index === 0 ? datasetLabel(network) : '',\n toolLine,\n ])\n )\n })\n return [row(headers), widths.map((width) => '-'.repeat(width)).join(' '), ...networkRows].join(\n '\\n'\n )\n}\n"],"mappings":";;;;;;;;;AAiDA,MAAa,oCAAoC;CAC/C,kBAAkB;CAClB,aAAa;CACb,mBAAmB;CACnB,2BAA2B;CAC3B,mBAAmB;CACnB,WAAW;CACX,gBAAgB;AAClB;AACA,MAAM,2BAA2B;AAEjC,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,kBAAkB,KAAwC;CACjE,IAAI,CAAC,SAAS,GAAG,KAAK,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,KAAK,MAAM,IAC9E,OAAO;CAET,MAAM,UAAU,IAAI,QAAQ,KAAK;CACjC,MAAM,aAAgC;EACpC;EACA,cACE,OAAO,IAAI,iBAAiB,YAAY,IAAI,aAAa,KAAK,MAAM,KAChE,IAAI,eACJ;EACN,QAAQ,OAAO,IAAI,WAAW,YAAY,IAAI,OAAO,KAAK,MAAM,KAAK,IAAI,SAAS;EAClF,QAAQ,CAAC;EACT,OAAO,EAAE,GAAG,kCAAkC;CAChD;CACA,IAAI,IAAI,YAAY,MAAM,WAAW,UAAU;CAC/C,IAAI,IAAI,YAAY,OAAO,WAAW,UAAU;CAChD,IAAI,SAAS,IAAI,QAAQ,GAAG,WAAW,WAAW,IAAI;CACtD,IAAI,SAAS,IAAI,SAAS,GACxB,WAAW,YAAY,IAAI;CAC7B,OAAO;AACT;;AAGA,SAAgB,+BAA+B,UAEf;CAC9B,OAAO;EACL,QAAQ;EACR,UAAU,SAAS,SAChB,KAAK,YAAY,kBAAkB,OAAO,CAAC,CAAC,CAC5C,QAAQ,YAA0C,YAAY,IAAI;CACvE;AACF;AAEA,SAAS,0BACP,UAC6B;CAC7B,OAAO,+BAA+B,QAAQ;AAChD;AAEA,SAAS,oBAAoB,UAAuB;CAClD,MAAM,MAAM,IAAI,IAAI,QAAQ;CAC5B,IAAI,WAAW;CACf,IAAI,SAAS;CACb,IAAI,OAAO;CACX,OAAO;AACT;AAEA,eAAsB,yBACpB,QACsC;CAEtC,MAAM,UAAU,oBADC,wBAAwB,MACE,CAAC;CAC5C,MAAM,UAAU,IAAI,QAAQ;CAC5B,MAAM,QAAQ,OAAO,mBAAmB,KAAK;CAC7C,IAAI,OACF,oBAAoB,SAAS,KAAK;CAEpC,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,MAAM,SAAS,EAAE,QAAQ,CAAC;CAC7C,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,uCAAuC,QAAQ,IAAK,IAAc,SAAS;CAC7F;CACA,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,uCAAuC,QAAQ,SAAS,SAAS,QAAQ;CAE3F,MAAM,SAAU,MAAM,SAAS,KAAK;CACpC,IACE,OAAO,WAAW,4CAClB,CAAC,MAAM,QAAQ,OAAO,QAAQ,GAE9B,MAAM,IAAI,MAAM,sDAAsD;CAExE,OAAO,0BAA0B,MAAM;AACzC;AAEA,SAAS,eAAe,SAAsC;CAC5D,MAAM,iBAAiB;EACrB,GAAI,QAAQ,SAAS,CAAC;EACtB,GAAG;CACL;CAIA,OAHc,OAAO,QAAQ,cAAc,CAAC,CACzC,QAAQ,GAAG,YAAY,WAAW,WAAW,CAAC,CAC9C,KAAK,CAAC,UAAU,IACR,CAAC,CAAC,KAAK;AACpB;AAEA,SAAS,mBAAmB,SAAsC;CAChE,MAAM,QAAQ,eAAe,OAAO;CACpC,IAAI,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM;CACtC,MAAM,QAAkB,CAAC;CACzB,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,0BACjD,MAAM,KAAK,MAAM,MAAM,OAAO,QAAQ,wBAAwB,CAAC,CAAC,KAAK,IAAI,CAAC;CAE5E,OAAO;AACT;AAEA,SAAS,UAAU,OAAwB;CACzC,IAAI,CAAC,OAAO,OAAO;CACnB,OAAO,MAAM,MAAM,GAAG,EAAE;AAC1B;AAEA,SAAS,aAAa,SAAoC;CACxD,MAAM,WAAW,QAAQ;CACzB,IAAI,CAAC,UAAU,OAAO;CACtB,MAAM,aACJ,SAAS,eAAe,KAAA,KAAa,SAAS,aAAa,KAAA,IACvD,GAAG,SAAS,WAAW,IAAI,SAAS,aACpC;CACN,MAAM,YACJ,SAAS,kBAAkB,SAAS,eAChC,GAAG,UAAU,SAAS,cAAc,EAAE,IAAI,UAAU,SAAS,YAAY,MACzE;CACN,IAAI,eAAe,oBAAoB,cAAc,IAAI,OAAO;CAChE,IAAI,eAAe,kBAAkB,OAAO;CAC5C,IAAI,cAAc,IAAI,OAAO;CAC7B,OAAO,GAAG,WAAW,KAAK;AAC5B;AAEA,SAAgB,0BAA0B,UAA+C;CACvF,IAAI,SAAS,SAAS,WAAW,GAAG,OAAO;CAC3C,MAAM,UAAU;EAAC;EAAW;EAAW;CAAiB;CACxD,MAAM,SAAS;EAAC;EAAI;EAAI;CAAE;CAC1B,MAAM,OAAO,WACX,OAAO,KAAK,OAAO,UAAU,MAAM,OAAO,OAAO,MAAO,CAAC,CAAC,CAAC,KAAK,IAAI;CACtE,MAAM,cAAc,SAAS,SAAS,SAAS,YAAY;EAEzD,OADkB,mBAAmB,OACtB,CAAC,CAAC,KAAK,UAAU,UAC9B,IAAI;GACF,UAAU,IAAI,QAAQ,gBAAgB,QAAQ,UAAU;GACxD,UAAU,IAAI,aAAa,OAAO,IAAI;GACtC;EACF,CAAC,CACH;CACF,CAAC;CACD,OAAO;EAAC,IAAI,OAAO;EAAG,OAAO,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;EAAG,GAAG;CAAW,CAAC,CAAC,KACzF,IACF;AACF"}
1
+ {"version":3,"file":"capabilities-BPnw6nP_.mjs","names":[],"sources":["../src/mcp/capabilities.ts"],"sourcesContent":["import type { InvestigatorConfig } from '../config/schema.js'\nimport { applyMcpAuthHeaders, resolveGraphMcpEndpoint } from './client.js'\n\nexport interface NetworkTopologyLayer {\n enabled: boolean\n coverage?: {\n from_block?: number\n to_block?: number\n from_timestamp?: string\n to_timestamp?: string\n chain_tip_block?: number\n blocks_behind_tip?: number\n }\n}\n\nexport interface NetworkLayerCapability {\n enabled: boolean\n live?: NetworkTopologyLayer\n archive?: NetworkTopologyLayer\n}\n\nexport interface NetworkCapability {\n network: string\n display_name?: string\n status: string\n default?: boolean\n layers: Record<string, NetworkLayerCapability>\n tools: Record<string, string>\n coverage?: {\n from_block?: number\n to_block?: number\n from_timestamp?: string\n to_timestamp?: string\n chain_tip_block?: number\n blocks_behind_tip?: number\n }\n freshness?: {\n last_processed_at?: string\n last_successful_sync_at?: string\n max_data_age_seconds?: number\n last_processing_duration_seconds?: number\n }\n}\n\nexport interface NetworkCapabilitiesDocument {\n schema: 'chain-insights.network-capabilities.v1'\n networks: NetworkCapability[]\n}\n\nexport const PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS = {\n aml_address_risk: 'available',\n graph_query: 'available',\n graph_query_batch: 'available',\n meta_network_capabilities: 'available',\n meta_usage_status: 'available',\n meta_help: 'available',\n wallet_balance: 'available',\n} as const\nconst AVAILABLE_TOOLS_PER_LINE = 3\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction advertisedNetwork(raw: unknown): NetworkCapability | null {\n if (!isRecord(raw) || typeof raw.network !== 'string' || raw.network.trim() === '') {\n return null\n }\n const network = raw.network.trim()\n const capability: NetworkCapability = {\n network,\n display_name:\n typeof raw.display_name === 'string' && raw.display_name.trim() !== ''\n ? raw.display_name\n : network,\n status: typeof raw.status === 'string' && raw.status.trim() !== '' ? raw.status : 'live',\n layers: {},\n tools: { ...PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS },\n }\n if (raw.default === true) capability.default = true\n if (raw.default === false) capability.default = false\n if (isRecord(raw.coverage)) capability.coverage = raw.coverage as NetworkCapability['coverage']\n if (isRecord(raw.freshness))\n capability.freshness = raw.freshness as NetworkCapability['freshness']\n return capability\n}\n\n/** Repeat GraphRAG's network list. CIA does not add, drop, or invent names. */\nexport function mirrorGraphNetworkCapabilities(document: {\n networks: unknown[]\n}): NetworkCapabilitiesDocument {\n return {\n schema: 'chain-insights.network-capabilities.v1',\n networks: document.networks\n .map((network) => advertisedNetwork(network))\n .filter((network): network is NetworkCapability => network !== null),\n }\n}\n\nfunction publicNetworkCapabilities(\n document: NetworkCapabilitiesDocument\n): NetworkCapabilitiesDocument {\n return mirrorGraphNetworkCapabilities(document)\n}\n\nfunction metadataNetworksUrl(endpoint: string): URL {\n const url = new URL(endpoint)\n url.pathname = '/metadata/networks'\n url.search = ''\n url.hash = ''\n return url\n}\n\nexport async function fetchNetworkCapabilities(\n config: Pick<InvestigatorConfig, 'graphMcpAuthToken' | 'graphMcpMode' | 'graphMcpEndpoint'>\n): Promise<NetworkCapabilitiesDocument> {\n const endpoint = resolveGraphMcpEndpoint(config)\n const request = metadataNetworksUrl(endpoint)\n const headers = new Headers()\n const token = config.graphMcpAuthToken?.trim()\n if (token) {\n applyMcpAuthHeaders(headers, token)\n }\n let response: Response\n try {\n response = await fetch(request, { headers })\n } catch (err) {\n throw new Error(`network capabilities unavailable at ${request}: ${(err as Error).message}`)\n }\n if (!response.ok) {\n throw new Error(`network capabilities unavailable at ${request}: HTTP ${response.status}`)\n }\n const parsed = (await response.json()) as NetworkCapabilitiesDocument\n if (\n parsed.schema !== 'chain-insights.network-capabilities.v1' ||\n !Array.isArray(parsed.networks)\n ) {\n throw new Error('network capabilities response has unsupported schema')\n }\n return publicNetworkCapabilities(parsed)\n}\n\nfunction availableTools(network: NetworkCapability): string[] {\n const effectiveTools = {\n ...(network.tools ?? {}),\n ...PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS,\n }\n const tools = Object.entries(effectiveTools)\n .filter(([, status]) => status === 'available')\n .map(([name]) => name)\n return tools.sort()\n}\n\nfunction availableToolLines(network: NetworkCapability): string[] {\n const tools = availableTools(network)\n if (tools.length === 0) return ['none']\n const lines: string[] = []\n for (let index = 0; index < tools.length; index += AVAILABLE_TOOLS_PER_LINE) {\n lines.push(tools.slice(index, index + AVAILABLE_TOOLS_PER_LINE).join(', '))\n }\n return lines\n}\n\nfunction shortDate(value?: string): string {\n if (!value) return ''\n return value.slice(0, 10)\n}\n\nfunction datasetLabel(network: NetworkCapability): string {\n const coverage = network.coverage\n if (!coverage) return 'unknown'\n const blockRange =\n coverage.from_block !== undefined && coverage.to_block !== undefined\n ? `${coverage.from_block}..${coverage.to_block}`\n : 'blocks unknown'\n const dateRange =\n coverage.from_timestamp && coverage.to_timestamp\n ? `${shortDate(coverage.from_timestamp)}..${shortDate(coverage.to_timestamp)}`\n : ''\n if (blockRange === 'blocks unknown' && dateRange === '') return 'unknown'\n if (blockRange === 'blocks unknown') return dateRange\n if (dateRange === '') return blockRange\n return `${blockRange} / ${dateRange}`\n}\n\nexport function formatNetworkCapabilities(document: NetworkCapabilitiesDocument): string {\n if (document.networks.length === 0) return 'No supported networks advertised.'\n const headers = ['Network', 'Dataset', 'Available tools']\n const widths = [14, 38, 64]\n const row = (values: string[]) =>\n values.map((value, index) => value.padEnd(widths[index]!)).join(' ')\n const networkRows = document.networks.flatMap((network) => {\n const toolLines = availableToolLines(network)\n return toolLines.map((toolLine, index) =>\n row([\n index === 0 ? network.display_name || network.network : '',\n index === 0 ? datasetLabel(network) : '',\n toolLine,\n ])\n )\n })\n return [row(headers), widths.map((width) => '-'.repeat(width)).join(' '), ...networkRows].join(\n '\\n'\n )\n}\n\nexport function findNetworkCapability(\n document: NetworkCapabilitiesDocument,\n name: string\n): NetworkCapability | undefined {\n const normalizedName = name.trim().toLowerCase()\n if (!normalizedName) return undefined\n return document.networks.find((network) =>\n [network.network, network.display_name].some(\n (candidate) => candidate?.trim().toLowerCase() === normalizedName\n )\n )\n}\n\nexport function formatNetworkCapability(network: NetworkCapability): string {\n const rows = [\n ['Network', network.display_name || network.network],\n ['Identifier', network.network],\n ['Status', network.default ? `${network.status} (default)` : network.status],\n ['Dataset', datasetLabel(network)],\n ['Available tools', availableTools(network).join(', ') || 'none'],\n ]\n const labelWidth = Math.max(...rows.map(([label]) => label.length))\n return rows.map(([label, value]) => `${label.padEnd(labelWidth)} ${value}`).join('\\n')\n}\n"],"mappings":"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"}
@@ -1,10 +1,12 @@
1
1
  const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
- const require_client = require("./client-CqAzD519.cjs");
2
+ const require_client = require("./client-Ypw9BNbn.cjs");
3
3
  //#region src/mcp/capabilities.ts
4
4
  var capabilities_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
5
5
  PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS: () => PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS,
6
6
  fetchNetworkCapabilities: () => fetchNetworkCapabilities,
7
+ findNetworkCapability: () => findNetworkCapability,
7
8
  formatNetworkCapabilities: () => formatNetworkCapabilities,
9
+ formatNetworkCapability: () => formatNetworkCapability,
8
10
  mirrorGraphNetworkCapabilities: () => mirrorGraphNetworkCapabilities
9
11
  });
10
12
  const PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS = {
@@ -123,6 +125,22 @@ function formatNetworkCapabilities(document) {
123
125
  ...networkRows
124
126
  ].join("\n");
125
127
  }
128
+ function findNetworkCapability(document, name) {
129
+ const normalizedName = name.trim().toLowerCase();
130
+ if (!normalizedName) return void 0;
131
+ return document.networks.find((network) => [network.network, network.display_name].some((candidate) => candidate?.trim().toLowerCase() === normalizedName));
132
+ }
133
+ function formatNetworkCapability(network) {
134
+ const rows = [
135
+ ["Network", network.display_name || network.network],
136
+ ["Identifier", network.network],
137
+ ["Status", network.default ? `${network.status} (default)` : network.status],
138
+ ["Dataset", datasetLabel(network)],
139
+ ["Available tools", availableTools(network).join(", ") || "none"]
140
+ ];
141
+ const labelWidth = Math.max(...rows.map(([label]) => label.length));
142
+ return rows.map(([label, value]) => `${label.padEnd(labelWidth)} ${value}`).join("\n");
143
+ }
126
144
  //#endregion
127
145
  Object.defineProperty(exports, "capabilities_exports", {
128
146
  enumerable: true,