chain-insights 0.3.7 → 0.3.11
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 +5 -0
- package/dist/{app-BxojXjtB.cjs → app-DjJn3irw.cjs} +1 -1
- package/dist/{app-CRd39JJ8.mjs → app-norpwdou.mjs} +2 -2
- package/dist/{app-CRd39JJ8.mjs.map → app-norpwdou.mjs.map} +1 -1
- package/dist/{artifact-server-XbN16DwU.cjs → artifact-server-C6_gtIql.cjs} +1 -1
- package/dist/{artifact-server-CP6LXQ9d.mjs → artifact-server-DHPM0lxS.mjs} +2 -2
- package/dist/{artifact-server-CP6LXQ9d.mjs.map → artifact-server-DHPM0lxS.mjs.map} +1 -1
- package/dist/{capabilities-BC3Y5EOi.mjs → capabilities-BCvkTkIu.mjs} +3 -6
- package/dist/capabilities-BCvkTkIu.mjs.map +1 -0
- package/dist/{capabilities-D5PSx9Hj.cjs → capabilities-DOa6EFO-.cjs} +2 -5
- package/dist/cli.cjs +58 -31
- package/dist/cli.mjs +58 -31
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-D4JE7fFF.mjs → client-BgmHjBHQ.mjs} +15 -7
- package/dist/client-BgmHjBHQ.mjs.map +1 -0
- package/dist/{client-Db6IV1tv.cjs → client-Y_zqKqJT.cjs} +19 -5
- package/dist/{config-Drgc2HuF.mjs → config-C6zM8Xir.mjs} +3 -3
- package/dist/{config-Drgc2HuF.mjs.map → config-C6zM8Xir.mjs.map} +1 -1
- package/dist/{config-BwVx19Og.cjs → config-CkW404Cs.cjs} +2 -2
- package/dist/index.cjs +4 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/{init-CKQ6F07J.mjs → init-uAmPfio2.mjs} +2 -2
- package/dist/{init-CKQ6F07J.mjs.map → init-uAmPfio2.mjs.map} +1 -1
- package/dist/{init-Dhw8F23z.cjs → init-vj2v5PMP.cjs} +1 -1
- package/dist/{mcp-endpoint-DHs1cRFH.mjs → mcp-endpoint-QQ5Lbqc2.mjs} +5 -2
- package/dist/mcp-endpoint-QQ5Lbqc2.mjs.map +1 -0
- package/dist/{mcp-endpoint-BaV8h_lq.cjs → mcp-endpoint-cQIZSjkK.cjs} +4 -1
- package/dist/mcp-proxy.cjs +444 -410
- package/dist/mcp-proxy.d.cts +3 -1
- package/dist/mcp-proxy.d.cts.map +1 -1
- package/dist/mcp-proxy.d.mts +3 -1
- package/dist/mcp-proxy.d.mts.map +1 -1
- package/dist/mcp-proxy.mjs +444 -411
- package/dist/mcp-proxy.mjs.map +1 -1
- package/dist/{public-tools-xfVNz9NE.cjs → public-tools-BY3PTw6x.cjs} +59 -31
- package/dist/{public-tools-CyUZEz9B.mjs → public-tools-CvlZcysd.mjs} +60 -32
- package/dist/public-tools-CvlZcysd.mjs.map +1 -0
- package/dist/{runner-DWuSy1Se.mjs → runner-B9fXAP0t.mjs} +3 -3
- package/dist/{runner-DWuSy1Se.mjs.map → runner-B9fXAP0t.mjs.map} +1 -1
- package/dist/{runner-CVo41fjz.cjs → runner-CcZCrrkn.cjs} +2 -2
- package/dist/{schema-BFEWhzg7.mjs → schema-D_qwaQA5.mjs} +2 -2
- package/dist/{schema-BFEWhzg7.mjs.map → schema-D_qwaQA5.mjs.map} +1 -1
- package/dist/{schema-Vl9yuOFO.cjs → schema-Dr6JXSOF.cjs} +1 -1
- package/dist/{server-BXLX2j_A.mjs → server-86dyCsJO.mjs} +2 -2
- package/dist/{server-BXLX2j_A.mjs.map → server-86dyCsJO.mjs.map} +1 -1
- package/dist/{server-BqVdWath.cjs → server-B2NFmnCM.cjs} +1 -1
- package/dist/update-BJoXYucO.cjs +145 -0
- package/dist/update-CJUfGCxs.mjs +145 -0
- package/dist/update-CJUfGCxs.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/capabilities-BC3Y5EOi.mjs.map +0 -1
- package/dist/client-D4JE7fFF.mjs.map +0 -1
- package/dist/mcp-endpoint-DHs1cRFH.mjs.map +0 -1
- package/dist/public-tools-CyUZEz9B.mjs.map +0 -1
package/dist/mcp-proxy.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-DakpK96I.cjs");
|
|
3
3
|
const require_version = require("./version-CO9Or_YV.cjs");
|
|
4
|
-
const require_client = require("./client-
|
|
4
|
+
const require_client = require("./client-Y_zqKqJT.cjs");
|
|
5
5
|
const require_tool_visibility = require("./tool-visibility-Buq7YdUZ.cjs");
|
|
6
6
|
let node_url = require("node:url");
|
|
7
7
|
let node_path = require("node:path");
|
|
@@ -45,6 +45,12 @@ const GRAPH_ARRAY_KEYS = [
|
|
|
45
45
|
"edge_anchors"
|
|
46
46
|
];
|
|
47
47
|
const __dirname$1 = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
|
|
48
|
+
function resolveMcpProxyMode(env = process.env) {
|
|
49
|
+
const raw = env["CHAIN_INSIGHTS_MCP_PROXY_MODE"]?.trim().toLowerCase();
|
|
50
|
+
if (!raw || raw === "workspace") return "workspace";
|
|
51
|
+
if (raw === "stateless" || raw === "no-workspace" || raw === "workspace-less") return "stateless";
|
|
52
|
+
throw new Error(`CHAIN_INSIGHTS_MCP_PROXY_MODE must be workspace or stateless; got "${raw}"`);
|
|
53
|
+
}
|
|
48
54
|
const COMMA_SEPARATED_ADDRESS_FIELDS = new Set([
|
|
49
55
|
"victim_addresses",
|
|
50
56
|
"known_suspect_addresses",
|
|
@@ -117,6 +123,13 @@ const SERVER_INSTRUCTIONS = [
|
|
|
117
123
|
GRAPH_SCHEMA_HINTS,
|
|
118
124
|
"Presentation rules: preserve tool summaries as returned; never truncate blockchain addresses; use case tools to preserve evidence when a case exists."
|
|
119
125
|
].join("\n\n");
|
|
126
|
+
const STATELESS_SERVER_INSTRUCTIONS = [
|
|
127
|
+
"Chain Insights is running as a stateless AML proxy for a host application.",
|
|
128
|
+
"Do not use local case, evidence, dossier, session, wallet, or graph report workflows in this mode.",
|
|
129
|
+
"Use network_capabilities first when network support is unknown, then call address_risk, stake_insights, trace_victim_funds, trace_suspect_funds, trace_deposit_sources, graph_query, or graph_query_batch as needed.",
|
|
130
|
+
GRAPH_SCHEMA_HINTS,
|
|
131
|
+
"Presentation rules: preserve tool summaries as returned; never truncate blockchain addresses."
|
|
132
|
+
].join("\n\n");
|
|
120
133
|
function readGraphAppHtml() {
|
|
121
134
|
const candidates = [
|
|
122
135
|
node_path.default.resolve(__dirname$1, "templates", "graph.html"),
|
|
@@ -570,12 +583,12 @@ function getRemoteGraphPayload(result) {
|
|
|
570
583
|
if (!data || typeof data !== "object" || Array.isArray(data)) throw new Error("Invalid remote graph payload");
|
|
571
584
|
return data;
|
|
572
585
|
}
|
|
573
|
-
async function normalizeRemoteToolResult(result, config, toolName = "remote-graph") {
|
|
586
|
+
async function normalizeRemoteToolResult(result, config, toolName = "remote-graph", includeAttachments = true) {
|
|
574
587
|
const graphPayload = getRemoteGraphPayload(result);
|
|
575
588
|
const meta = { ...result._meta ?? {} };
|
|
576
|
-
if (graphPayload) {
|
|
589
|
+
if (graphPayload && includeAttachments) {
|
|
577
590
|
const { writeGraphReport } = await Promise.resolve().then(() => require("./graph-reports-B3mkLP8Z.cjs"));
|
|
578
|
-
const { ensureArtifactServer } = await Promise.resolve().then(() => require("./artifact-server-
|
|
591
|
+
const { ensureArtifactServer } = await Promise.resolve().then(() => require("./artifact-server-C6_gtIql.cjs"));
|
|
579
592
|
const report = await writeGraphReport(graphPayload, {
|
|
580
593
|
serverPort: config.serverPort,
|
|
581
594
|
slug: toolName || "remote-graph"
|
|
@@ -596,6 +609,26 @@ async function normalizeRemoteToolResult(result, config, toolName = "remote-grap
|
|
|
596
609
|
isError: result.isError
|
|
597
610
|
};
|
|
598
611
|
}
|
|
612
|
+
function shouldIncludeAttachments(args, workspaceArtifactsEnabled) {
|
|
613
|
+
return workspaceArtifactsEnabled && args["include_attachments"] !== false;
|
|
614
|
+
}
|
|
615
|
+
async function writeLocalGraphMeta(graphData, config, slug, includeAttachments) {
|
|
616
|
+
if (!includeAttachments) return void 0;
|
|
617
|
+
const { writeGraphReport } = await Promise.resolve().then(() => require("./graph-reports-B3mkLP8Z.cjs"));
|
|
618
|
+
const { ensureArtifactServer } = await Promise.resolve().then(() => require("./artifact-server-C6_gtIql.cjs"));
|
|
619
|
+
const report = await writeGraphReport(graphData, {
|
|
620
|
+
serverPort: config.serverPort,
|
|
621
|
+
slug
|
|
622
|
+
});
|
|
623
|
+
await ensureArtifactServer(config.serverPort);
|
|
624
|
+
return {
|
|
625
|
+
schema: report.schema,
|
|
626
|
+
url: report.url
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
function graphMetaResult(graph) {
|
|
630
|
+
return graph ? { chainInsights: { graph } } : void 0;
|
|
631
|
+
}
|
|
599
632
|
/**
|
|
600
633
|
* Core proxy logic — exported so tests can inject dependencies directly.
|
|
601
634
|
* The IIFE at the bottom calls this with real dependencies.
|
|
@@ -604,20 +637,23 @@ async function normalizeRemoteToolResult(result, config, toolName = "remote-grap
|
|
|
604
637
|
* All diagnostic output goes to console.error() or process.stderr.write().
|
|
605
638
|
*/
|
|
606
639
|
async function createProxy() {
|
|
607
|
-
const { loadConfig } = await Promise.resolve().then(() => require("./config-
|
|
640
|
+
const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
|
|
608
641
|
const { activeDataDir, findActiveWorkspace } = await Promise.resolve().then(() => require("./active-BVr55kvW.cjs")).then((n) => n.active_exports);
|
|
609
|
-
const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-
|
|
642
|
+
const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Y_zqKqJT.cjs")).then((n) => n.client_exports);
|
|
610
643
|
const { loadSchema, saveSchema } = await Promise.resolve().then(() => require("./schema-cache-CJk1EL3L.cjs"));
|
|
644
|
+
const proxyMode = resolveMcpProxyMode();
|
|
645
|
+
const workspaceArtifactsEnabled = proxyMode === "workspace";
|
|
611
646
|
const loadedConfig = await loadConfig();
|
|
612
|
-
const activeWorkspace = findActiveWorkspace();
|
|
647
|
+
const activeWorkspace = workspaceArtifactsEnabled ? findActiveWorkspace() : null;
|
|
613
648
|
const config = {
|
|
614
649
|
...loadedConfig,
|
|
615
|
-
dataDir: activeDataDir(loadedConfig.dataDir)
|
|
650
|
+
dataDir: workspaceArtifactsEnabled ? activeDataDir(loadedConfig.dataDir) : loadedConfig.dataDir
|
|
616
651
|
};
|
|
617
652
|
const logger = createMcpLogger(config);
|
|
618
653
|
await logger.info("proxy.start", {
|
|
619
654
|
data_dir: config.dataDir,
|
|
620
655
|
workspace_root: activeWorkspace?.root,
|
|
656
|
+
proxy_mode: proxyMode,
|
|
621
657
|
graph_mcp_mode: config.graphMcpMode,
|
|
622
658
|
graph_mcp_endpoint: resolveGraphMcpEndpoint(config),
|
|
623
659
|
log_path: logger.filePath
|
|
@@ -694,7 +730,7 @@ async function createProxy() {
|
|
|
694
730
|
const server = new _modelcontextprotocol_sdk_server_mcp_js.McpServer({
|
|
695
731
|
name: "chain-insights",
|
|
696
732
|
version: require_version.PACKAGE_VERSION
|
|
697
|
-
}, { instructions: SERVER_INSTRUCTIONS });
|
|
733
|
+
}, { instructions: workspaceArtifactsEnabled ? SERVER_INSTRUCTIONS : STATELESS_SERVER_INSTRUCTIONS });
|
|
698
734
|
installToolLogging(server, logger);
|
|
699
735
|
const remotePrompts = [];
|
|
700
736
|
if (remoteConnected) try {
|
|
@@ -722,337 +758,339 @@ async function createProxy() {
|
|
|
722
758
|
if (typeof tags === "string") return tags.split(",").map((tag) => tag.trim()).filter(Boolean);
|
|
723
759
|
return [];
|
|
724
760
|
};
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
761
|
+
if (workspaceArtifactsEnabled) {
|
|
762
|
+
server.registerTool("balance", {
|
|
763
|
+
description: "Show the local Chain Insights payment wallet address and Base USDC balance.",
|
|
764
|
+
inputSchema: zod.object({}).passthrough()
|
|
765
|
+
}, async () => {
|
|
766
|
+
try {
|
|
767
|
+
const { getWalletAccount, getWalletBalanceText } = await Promise.resolve().then(() => require("./tools-BhTI3Lmg.cjs")).then((n) => n.tools_exports);
|
|
768
|
+
return {
|
|
769
|
+
content: [{
|
|
770
|
+
type: "text",
|
|
771
|
+
text: await getWalletBalanceText(await getWalletAccount())
|
|
772
|
+
}],
|
|
773
|
+
isError: false
|
|
774
|
+
};
|
|
775
|
+
} catch (err) {
|
|
776
|
+
return {
|
|
777
|
+
content: [{
|
|
778
|
+
type: "text",
|
|
779
|
+
text: `Balance failed: ${err.message}`
|
|
780
|
+
}],
|
|
781
|
+
isError: true
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
(0, _modelcontextprotocol_ext_apps_server.registerAppResource)(server, "Fund Flow Graph", GRAPH_RESOURCE_URI, {
|
|
786
|
+
description: "Interactive D3 force-directed graph for fund flow and pattern visualization. It loads local graph report URLs returned in _meta.chainInsights.graph.url.",
|
|
787
|
+
_meta: { ui: { csp: {
|
|
788
|
+
resourceDomains: graphArtifactOrigins(config),
|
|
789
|
+
connectDomains: graphArtifactOrigins(config)
|
|
790
|
+
} } }
|
|
791
|
+
}, async () => ({ contents: [{
|
|
792
|
+
uri: GRAPH_RESOURCE_URI,
|
|
793
|
+
mimeType: _modelcontextprotocol_ext_apps_server.RESOURCE_MIME_TYPE,
|
|
794
|
+
text: readGraphAppHtml(),
|
|
795
|
+
_meta: { ui: { csp: {
|
|
796
|
+
resourceDomains: graphArtifactOrigins(config),
|
|
797
|
+
connectDomains: graphArtifactOrigins(config)
|
|
798
|
+
} } }
|
|
799
|
+
}] }));
|
|
800
|
+
server.registerTool("case_open", {
|
|
801
|
+
description: "Create a local Chain Insights investigation case. Use this before saving evidence, dossiers, or session notes for a new investigation.",
|
|
802
|
+
inputSchema: {
|
|
803
|
+
name: zod.string().min(1).describe("Case name"),
|
|
804
|
+
tags: zod.union([zod.string(), zod.array(zod.string())]).optional().describe("Comma-separated tags or string array"),
|
|
805
|
+
description: zod.string().optional().describe("Brief investigation description")
|
|
806
|
+
},
|
|
807
|
+
annotations: {
|
|
808
|
+
readOnlyHint: false,
|
|
809
|
+
destructiveHint: false,
|
|
810
|
+
idempotentHint: false,
|
|
811
|
+
openWorldHint: false
|
|
812
|
+
}
|
|
813
|
+
}, async ({ name, tags, description }) => {
|
|
814
|
+
try {
|
|
815
|
+
const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
816
|
+
const created = await CaseStore.create({
|
|
817
|
+
name,
|
|
818
|
+
tags: parseTags(tags),
|
|
819
|
+
description: description ?? ""
|
|
820
|
+
});
|
|
821
|
+
const { casesRoot } = await Promise.resolve().then(() => require("./store-CQhU8dz8.cjs")).then((n) => n.store_exports);
|
|
822
|
+
return {
|
|
823
|
+
content: [{
|
|
824
|
+
type: "text",
|
|
825
|
+
text: JSON.stringify({
|
|
826
|
+
case_id: created.id,
|
|
827
|
+
name: created.name,
|
|
828
|
+
status: created.status,
|
|
829
|
+
tags: created.tags,
|
|
830
|
+
directory: `${node_path.default.join(casesRoot(), created.id)}/`
|
|
831
|
+
}, null, 2)
|
|
832
|
+
}],
|
|
833
|
+
isError: false
|
|
834
|
+
};
|
|
835
|
+
} catch (err) {
|
|
836
|
+
return caseToolError("Case open", err);
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
server.registerTool("case_list", {
|
|
840
|
+
description: "List local Chain Insights investigation cases. Use before resuming when the user does not provide a case ID.",
|
|
841
|
+
inputSchema: { status: zod.enum([
|
|
842
|
+
"open",
|
|
843
|
+
"active",
|
|
844
|
+
"suspended",
|
|
845
|
+
"closed"
|
|
846
|
+
]).optional().describe("Optional status filter") },
|
|
847
|
+
annotations: {
|
|
848
|
+
readOnlyHint: true,
|
|
849
|
+
destructiveHint: false,
|
|
850
|
+
idempotentHint: true,
|
|
851
|
+
openWorldHint: false
|
|
852
|
+
}
|
|
853
|
+
}, async ({ status }) => {
|
|
854
|
+
try {
|
|
855
|
+
const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
856
|
+
const cases = await CaseStore.list();
|
|
857
|
+
const filtered = status ? cases.filter((entry) => entry.status === status) : cases;
|
|
858
|
+
return {
|
|
859
|
+
content: [{
|
|
860
|
+
type: "text",
|
|
861
|
+
text: JSON.stringify({ cases: filtered }, null, 2)
|
|
862
|
+
}],
|
|
863
|
+
isError: false
|
|
864
|
+
};
|
|
865
|
+
} catch (err) {
|
|
866
|
+
return caseToolError("Case list", err);
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
server.registerTool("case_resume", {
|
|
870
|
+
description: "Load local Chain Insights case context: metadata, evidence count, dossier summaries, and latest session notes.",
|
|
871
|
+
inputSchema: { case_id: zod.string().min(1).describe("Chain Insights case ID") },
|
|
872
|
+
annotations: {
|
|
873
|
+
readOnlyHint: true,
|
|
874
|
+
destructiveHint: false,
|
|
875
|
+
idempotentHint: true,
|
|
876
|
+
openWorldHint: false
|
|
877
|
+
}
|
|
878
|
+
}, async ({ case_id }) => {
|
|
879
|
+
try {
|
|
880
|
+
const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
881
|
+
const context = await CaseStore.loadContext(case_id);
|
|
882
|
+
return {
|
|
883
|
+
content: [{
|
|
884
|
+
type: "text",
|
|
885
|
+
text: JSON.stringify(context, null, 2)
|
|
886
|
+
}],
|
|
887
|
+
isError: false
|
|
888
|
+
};
|
|
889
|
+
} catch (err) {
|
|
890
|
+
return caseToolError("Case resume", err);
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
server.registerTool("case_add_evidence", {
|
|
894
|
+
description: "Append a tool result or analyst note to a local case evidence manifest. Use after address_risk, trace_victim_funds, trace_suspect_funds, trace_deposit_sources, graph_query, or manual findings that should be preserved.",
|
|
895
|
+
inputSchema: {
|
|
896
|
+
case_id: zod.string().min(1).describe("Chain Insights case ID"),
|
|
897
|
+
source: zod.string().min(1).describe("Source tool or evidence origin"),
|
|
898
|
+
content: zod.string().min(1).describe("Evidence markdown/text to store"),
|
|
899
|
+
query_params: zod.string().optional().describe("Original query parameters, for example \"network=bittensor address=...\"")
|
|
900
|
+
},
|
|
901
|
+
annotations: {
|
|
902
|
+
readOnlyHint: false,
|
|
903
|
+
destructiveHint: false,
|
|
904
|
+
idempotentHint: false,
|
|
905
|
+
openWorldHint: false
|
|
906
|
+
}
|
|
907
|
+
}, async ({ case_id, source, content, query_params }) => {
|
|
908
|
+
try {
|
|
909
|
+
const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
910
|
+
const saved = await EvidenceStore.append(case_id, {
|
|
911
|
+
source,
|
|
912
|
+
content,
|
|
913
|
+
queryParams: query_params ?? ""
|
|
914
|
+
});
|
|
915
|
+
return {
|
|
916
|
+
content: [{
|
|
917
|
+
type: "text",
|
|
918
|
+
text: JSON.stringify(saved, null, 2)
|
|
919
|
+
}],
|
|
920
|
+
isError: false
|
|
921
|
+
};
|
|
922
|
+
} catch (err) {
|
|
923
|
+
return caseToolError("Evidence append", err);
|
|
924
|
+
}
|
|
925
|
+
});
|
|
926
|
+
server.registerTool("case_verify_evidence", {
|
|
927
|
+
description: "Verify a local case evidence manifest and report tampered or missing evidence files.",
|
|
928
|
+
inputSchema: { case_id: zod.string().min(1).describe("Chain Insights case ID") },
|
|
929
|
+
annotations: {
|
|
930
|
+
readOnlyHint: true,
|
|
931
|
+
destructiveHint: false,
|
|
932
|
+
idempotentHint: true,
|
|
933
|
+
openWorldHint: false
|
|
934
|
+
}
|
|
935
|
+
}, async ({ case_id }) => {
|
|
936
|
+
try {
|
|
937
|
+
const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
938
|
+
const result = await EvidenceStore.verifyManifest(case_id);
|
|
939
|
+
return {
|
|
940
|
+
content: [{
|
|
941
|
+
type: "text",
|
|
942
|
+
text: JSON.stringify(result, null, 2)
|
|
943
|
+
}],
|
|
944
|
+
isError: false
|
|
945
|
+
};
|
|
946
|
+
} catch (err) {
|
|
947
|
+
return caseToolError("Evidence verify", err);
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
server.registerTool("case_export", {
|
|
951
|
+
description: "Export a Chain Insights case to an Obsidian, LLM Wiki, Codex, Claude Code, and ChatGPT-friendly handoff bundle.",
|
|
952
|
+
inputSchema: {
|
|
953
|
+
case_id: zod.string().min(1).describe("Chain Insights case ID to export"),
|
|
954
|
+
target: zod.enum(["obsidian-llmwiki"]).optional().describe("Export target. Default obsidian-llmwiki."),
|
|
955
|
+
mode: zod.enum([
|
|
956
|
+
"private",
|
|
957
|
+
"partner",
|
|
958
|
+
"public"
|
|
959
|
+
]).optional().describe("Redaction mode. Default private."),
|
|
960
|
+
output_dir: zod.string().optional().describe("Optional output directory. Defaults to published/<case-slug>.")
|
|
961
|
+
},
|
|
962
|
+
annotations: {
|
|
963
|
+
readOnlyHint: false,
|
|
964
|
+
destructiveHint: false,
|
|
965
|
+
idempotentHint: false,
|
|
966
|
+
openWorldHint: false
|
|
967
|
+
}
|
|
968
|
+
}, async ({ case_id, target, mode, output_dir }) => {
|
|
969
|
+
try {
|
|
970
|
+
const { exportCase } = await Promise.resolve().then(() => require("./export-D4v4-6F4.cjs"));
|
|
971
|
+
const result = await exportCase({
|
|
972
|
+
caseId: case_id,
|
|
973
|
+
target: target ?? "obsidian-llmwiki",
|
|
974
|
+
mode: mode ?? "private",
|
|
975
|
+
outputDir: output_dir
|
|
976
|
+
});
|
|
977
|
+
return {
|
|
978
|
+
content: [{
|
|
979
|
+
type: "text",
|
|
980
|
+
text: [
|
|
981
|
+
`Case exported: ${result.outputDir}`,
|
|
982
|
+
`Manifest: ${result.manifestPath}`,
|
|
983
|
+
`Files: ${result.fileCount}`,
|
|
984
|
+
`Open first: ${result.nextFile}`,
|
|
985
|
+
...result.warnings.map((warning) => `Warning: ${warning}`)
|
|
986
|
+
].join("\n")
|
|
987
|
+
}],
|
|
988
|
+
structuredContent: result,
|
|
989
|
+
isError: false
|
|
990
|
+
};
|
|
991
|
+
} catch (err) {
|
|
992
|
+
return caseToolError("Case export", err);
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
server.registerTool("case_update_dossier", {
|
|
996
|
+
description: "Append a finding to an address/entity dossier inside a local Chain Insights case.",
|
|
997
|
+
inputSchema: {
|
|
998
|
+
case_id: zod.string().min(1).describe("Chain Insights case ID"),
|
|
999
|
+
address: zod.string().min(1).describe("Full address or entity identifier"),
|
|
1000
|
+
finding: zod.string().min(1).describe("Finding to append"),
|
|
1001
|
+
entity_type: zod.enum([
|
|
1002
|
+
"eoa",
|
|
1003
|
+
"contract",
|
|
1004
|
+
"exchange",
|
|
1005
|
+
"mixer",
|
|
1006
|
+
"unknown"
|
|
1007
|
+
]).optional().describe("Entity type")
|
|
1008
|
+
},
|
|
1009
|
+
annotations: {
|
|
1010
|
+
readOnlyHint: false,
|
|
1011
|
+
destructiveHint: false,
|
|
1012
|
+
idempotentHint: false,
|
|
1013
|
+
openWorldHint: false
|
|
1014
|
+
}
|
|
1015
|
+
}, async ({ case_id, address, finding, entity_type }) => {
|
|
1016
|
+
try {
|
|
1017
|
+
const { DossierStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
1018
|
+
await DossierStore.appendFinding(case_id, address, finding, entity_type ?? "unknown");
|
|
1019
|
+
return {
|
|
1020
|
+
content: [{
|
|
1021
|
+
type: "text",
|
|
1022
|
+
text: JSON.stringify({
|
|
1023
|
+
case_id,
|
|
1024
|
+
address,
|
|
1025
|
+
updated: true
|
|
1026
|
+
}, null, 2)
|
|
1027
|
+
}],
|
|
1028
|
+
isError: false
|
|
1029
|
+
};
|
|
1030
|
+
} catch (err) {
|
|
1031
|
+
return caseToolError("Dossier update", err);
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
server.registerTool("case_start_session", {
|
|
1035
|
+
description: "Start a local investigation session file for a Chain Insights case.",
|
|
1036
|
+
inputSchema: { case_id: zod.string().min(1).describe("Chain Insights case ID") },
|
|
1037
|
+
annotations: {
|
|
1038
|
+
readOnlyHint: false,
|
|
1039
|
+
destructiveHint: false,
|
|
1040
|
+
idempotentHint: false,
|
|
1041
|
+
openWorldHint: false
|
|
1042
|
+
}
|
|
1043
|
+
}, async ({ case_id }) => {
|
|
1044
|
+
try {
|
|
1045
|
+
const { SessionStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
1046
|
+
const session = await SessionStore.start(case_id);
|
|
1047
|
+
return {
|
|
1048
|
+
content: [{
|
|
1049
|
+
type: "text",
|
|
1050
|
+
text: JSON.stringify(session, null, 2)
|
|
1051
|
+
}],
|
|
1052
|
+
isError: false
|
|
1053
|
+
};
|
|
1054
|
+
} catch (err) {
|
|
1055
|
+
return caseToolError("Session start", err);
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
server.registerTool("case_end_session", {
|
|
1059
|
+
description: "End the latest local investigation session for a Chain Insights case with findings and next steps.",
|
|
1060
|
+
inputSchema: {
|
|
1061
|
+
case_id: zod.string().min(1).describe("Chain Insights case ID"),
|
|
1062
|
+
findings: zod.string().optional().describe("Key findings from this session"),
|
|
1063
|
+
next_steps: zod.string().optional().describe("Next investigation steps")
|
|
1064
|
+
},
|
|
1065
|
+
annotations: {
|
|
1066
|
+
readOnlyHint: false,
|
|
1067
|
+
destructiveHint: false,
|
|
1068
|
+
idempotentHint: false,
|
|
1069
|
+
openWorldHint: false
|
|
1070
|
+
}
|
|
1071
|
+
}, async ({ case_id, findings, next_steps }) => {
|
|
1072
|
+
try {
|
|
1073
|
+
const { SessionStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
1074
|
+
await SessionStore.end(case_id, {
|
|
1075
|
+
findings: findings ?? "",
|
|
1076
|
+
nextSteps: next_steps ?? ""
|
|
1077
|
+
});
|
|
1078
|
+
await SessionStore.archiveOldSessions(case_id);
|
|
1079
|
+
return {
|
|
1080
|
+
content: [{
|
|
1081
|
+
type: "text",
|
|
1082
|
+
text: JSON.stringify({
|
|
1083
|
+
case_id,
|
|
1084
|
+
ended: true
|
|
1085
|
+
}, null, 2)
|
|
1086
|
+
}],
|
|
1087
|
+
isError: false
|
|
1088
|
+
};
|
|
1089
|
+
} catch (err) {
|
|
1090
|
+
return caseToolError("Session end", err);
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1056
1094
|
if (!remoteToolNames.has("address_risk")) (0, _modelcontextprotocol_ext_apps_server.registerAppTool)(server, "address_risk", {
|
|
1057
1095
|
title: "Address Risk",
|
|
1058
1096
|
description: KNOWN_PUBLIC_TOOL_DESCRIPTIONS.address_risk,
|
|
@@ -1069,7 +1107,7 @@ async function createProxy() {
|
|
|
1069
1107
|
idempotentHint: true,
|
|
1070
1108
|
openWorldHint: true
|
|
1071
1109
|
}
|
|
1072
|
-
}, async ({ address, network, compare_address }) => {
|
|
1110
|
+
}, async ({ address, network, compare_address, include_attachments }) => {
|
|
1073
1111
|
try {
|
|
1074
1112
|
if (!remoteConnected) return {
|
|
1075
1113
|
content: [{
|
|
@@ -1078,29 +1116,20 @@ async function createProxy() {
|
|
|
1078
1116
|
}],
|
|
1079
1117
|
isError: true
|
|
1080
1118
|
};
|
|
1081
|
-
const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-
|
|
1082
|
-
const { writeGraphReport } = await Promise.resolve().then(() => require("./graph-reports-B3mkLP8Z.cjs"));
|
|
1083
|
-
const { ensureArtifactServer } = await Promise.resolve().then(() => require("./artifact-server-XbN16DwU.cjs"));
|
|
1119
|
+
const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
|
|
1084
1120
|
const result = await addressRisk(remoteClient, {
|
|
1085
1121
|
address,
|
|
1086
1122
|
network,
|
|
1087
1123
|
compareAddress: compare_address
|
|
1088
1124
|
});
|
|
1089
|
-
const
|
|
1090
|
-
serverPort: config.serverPort,
|
|
1091
|
-
slug: `address-risk-${network}-${address}`
|
|
1092
|
-
});
|
|
1093
|
-
await ensureArtifactServer(config.serverPort);
|
|
1125
|
+
const graph = await writeLocalGraphMeta(result.graphData, config, `address-risk-${network}-${address}`, shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled));
|
|
1094
1126
|
return {
|
|
1095
1127
|
content: [{
|
|
1096
1128
|
type: "text",
|
|
1097
1129
|
text: result.summaryText
|
|
1098
1130
|
}],
|
|
1099
1131
|
structuredContent: result.structuredContent,
|
|
1100
|
-
_meta:
|
|
1101
|
-
schema: report.schema,
|
|
1102
|
-
url: report.url
|
|
1103
|
-
} } },
|
|
1132
|
+
_meta: graphMetaResult(graph),
|
|
1104
1133
|
isError: false
|
|
1105
1134
|
};
|
|
1106
1135
|
} catch (err) {
|
|
@@ -1141,7 +1170,7 @@ async function createProxy() {
|
|
|
1141
1170
|
idempotentHint: false,
|
|
1142
1171
|
openWorldHint: true
|
|
1143
1172
|
}
|
|
1144
|
-
}, async ({ victim_addresses, known_suspect_addresses, network, case_id, incident_timestamp_ms, max_hops, per_address_limit, min_amount_sum }) => {
|
|
1173
|
+
}, async ({ victim_addresses, known_suspect_addresses, network, case_id, incident_timestamp_ms, max_hops, per_address_limit, min_amount_sum, include_attachments }) => {
|
|
1145
1174
|
try {
|
|
1146
1175
|
if (!remoteConnected) return {
|
|
1147
1176
|
content: [{
|
|
@@ -1150,9 +1179,14 @@ async function createProxy() {
|
|
|
1150
1179
|
}],
|
|
1151
1180
|
isError: true
|
|
1152
1181
|
};
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1182
|
+
if (!workspaceArtifactsEnabled && case_id) return {
|
|
1183
|
+
content: [{
|
|
1184
|
+
type: "text",
|
|
1185
|
+
text: "case_id requires Chain Insights workspace mode; omit case_id when CHAIN_INSIGHTS_MCP_PROXY_MODE=stateless."
|
|
1186
|
+
}],
|
|
1187
|
+
isError: true
|
|
1188
|
+
};
|
|
1189
|
+
const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
|
|
1156
1190
|
const result = await traceVictimFunds(remoteClient, config, {
|
|
1157
1191
|
victimAddresses: victim_addresses,
|
|
1158
1192
|
knownSuspectAddresses: known_suspect_addresses,
|
|
@@ -1161,23 +1195,17 @@ async function createProxy() {
|
|
|
1161
1195
|
incidentTimestampMs: incident_timestamp_ms,
|
|
1162
1196
|
maxHops: max_hops,
|
|
1163
1197
|
perAddressLimit: per_address_limit,
|
|
1164
|
-
minAmountSum: min_amount_sum
|
|
1165
|
-
|
|
1166
|
-
const report = await writeGraphReport(result.graphData, {
|
|
1167
|
-
serverPort: config.serverPort,
|
|
1168
|
-
slug: `trace-victim-funds-${network}`
|
|
1198
|
+
minAmountSum: min_amount_sum,
|
|
1199
|
+
writeArtifacts: workspaceArtifactsEnabled
|
|
1169
1200
|
});
|
|
1170
|
-
await
|
|
1201
|
+
const graph = await writeLocalGraphMeta(result.graphData, config, `trace-victim-funds-${network}`, shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled));
|
|
1171
1202
|
return {
|
|
1172
1203
|
content: [{
|
|
1173
1204
|
type: "text",
|
|
1174
1205
|
text: result.summaryText
|
|
1175
1206
|
}],
|
|
1176
1207
|
structuredContent: result.structuredContent,
|
|
1177
|
-
_meta:
|
|
1178
|
-
schema: report.schema,
|
|
1179
|
-
url: report.url
|
|
1180
|
-
} } },
|
|
1208
|
+
_meta: graphMetaResult(graph),
|
|
1181
1209
|
isError: false
|
|
1182
1210
|
};
|
|
1183
1211
|
} catch (err) {
|
|
@@ -1217,7 +1245,7 @@ async function createProxy() {
|
|
|
1217
1245
|
idempotentHint: false,
|
|
1218
1246
|
openWorldHint: true
|
|
1219
1247
|
}
|
|
1220
|
-
}, async ({ suspect_addresses, incident_timestamp_ms, network, max_hops, per_address_limit, min_amount_sum, case_id }) => {
|
|
1248
|
+
}, async ({ suspect_addresses, incident_timestamp_ms, network, max_hops, per_address_limit, min_amount_sum, case_id, include_attachments }) => {
|
|
1221
1249
|
try {
|
|
1222
1250
|
if (!remoteConnected) return {
|
|
1223
1251
|
content: [{
|
|
@@ -1226,9 +1254,14 @@ async function createProxy() {
|
|
|
1226
1254
|
}],
|
|
1227
1255
|
isError: true
|
|
1228
1256
|
};
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1257
|
+
if (!workspaceArtifactsEnabled && case_id) return {
|
|
1258
|
+
content: [{
|
|
1259
|
+
type: "text",
|
|
1260
|
+
text: "case_id requires Chain Insights workspace mode; omit case_id when CHAIN_INSIGHTS_MCP_PROXY_MODE=stateless."
|
|
1261
|
+
}],
|
|
1262
|
+
isError: true
|
|
1263
|
+
};
|
|
1264
|
+
const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
|
|
1232
1265
|
const result = await traceSuspectFunds(remoteClient, config, {
|
|
1233
1266
|
suspectAddresses: suspect_addresses,
|
|
1234
1267
|
network,
|
|
@@ -1236,23 +1269,17 @@ async function createProxy() {
|
|
|
1236
1269
|
perAddressLimit: per_address_limit,
|
|
1237
1270
|
minAmountSum: min_amount_sum,
|
|
1238
1271
|
incidentTimestampMs: incident_timestamp_ms,
|
|
1239
|
-
caseId: case_id
|
|
1240
|
-
|
|
1241
|
-
const report = await writeGraphReport(result.graphData, {
|
|
1242
|
-
serverPort: config.serverPort,
|
|
1243
|
-
slug: `trace-suspect-funds-${network}`
|
|
1272
|
+
caseId: case_id,
|
|
1273
|
+
writeArtifacts: workspaceArtifactsEnabled
|
|
1244
1274
|
});
|
|
1245
|
-
await
|
|
1275
|
+
const graph = await writeLocalGraphMeta(result.graphData, config, `trace-suspect-funds-${network}`, shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled));
|
|
1246
1276
|
return {
|
|
1247
1277
|
content: [{
|
|
1248
1278
|
type: "text",
|
|
1249
1279
|
text: result.summaryText
|
|
1250
1280
|
}],
|
|
1251
1281
|
structuredContent: result.structuredContent,
|
|
1252
|
-
_meta:
|
|
1253
|
-
schema: report.schema,
|
|
1254
|
-
url: report.url
|
|
1255
|
-
} } },
|
|
1282
|
+
_meta: graphMetaResult(graph),
|
|
1256
1283
|
isError: false
|
|
1257
1284
|
};
|
|
1258
1285
|
} catch (err) {
|
|
@@ -1289,7 +1316,7 @@ async function createProxy() {
|
|
|
1289
1316
|
idempotentHint: false,
|
|
1290
1317
|
openWorldHint: true
|
|
1291
1318
|
}
|
|
1292
|
-
}, async ({ deposit_addresses, network, max_hops, case_id }) => {
|
|
1319
|
+
}, async ({ deposit_addresses, network, max_hops, case_id, include_attachments }) => {
|
|
1293
1320
|
try {
|
|
1294
1321
|
if (!remoteConnected) return {
|
|
1295
1322
|
content: [{
|
|
@@ -1298,30 +1325,29 @@ async function createProxy() {
|
|
|
1298
1325
|
}],
|
|
1299
1326
|
isError: true
|
|
1300
1327
|
};
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1328
|
+
if (!workspaceArtifactsEnabled && case_id) return {
|
|
1329
|
+
content: [{
|
|
1330
|
+
type: "text",
|
|
1331
|
+
text: "case_id requires Chain Insights workspace mode; omit case_id when CHAIN_INSIGHTS_MCP_PROXY_MODE=stateless."
|
|
1332
|
+
}],
|
|
1333
|
+
isError: true
|
|
1334
|
+
};
|
|
1335
|
+
const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
|
|
1304
1336
|
const result = await traceDepositSources(remoteClient, config, {
|
|
1305
1337
|
depositAddresses: deposit_addresses,
|
|
1306
1338
|
network,
|
|
1307
1339
|
maxHops: max_hops,
|
|
1308
|
-
caseId: case_id
|
|
1309
|
-
|
|
1310
|
-
const report = await writeGraphReport(result.graphData, {
|
|
1311
|
-
serverPort: config.serverPort,
|
|
1312
|
-
slug: `trace-deposit-sources-${network}`
|
|
1340
|
+
caseId: case_id,
|
|
1341
|
+
writeArtifacts: workspaceArtifactsEnabled
|
|
1313
1342
|
});
|
|
1314
|
-
await
|
|
1343
|
+
const graph = await writeLocalGraphMeta(result.graphData, config, `trace-deposit-sources-${network}`, shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled));
|
|
1315
1344
|
return {
|
|
1316
1345
|
content: [{
|
|
1317
1346
|
type: "text",
|
|
1318
1347
|
text: result.summaryText
|
|
1319
1348
|
}],
|
|
1320
1349
|
structuredContent: result.structuredContent,
|
|
1321
|
-
_meta:
|
|
1322
|
-
schema: report.schema,
|
|
1323
|
-
url: report.url
|
|
1324
|
-
} } },
|
|
1350
|
+
_meta: graphMetaResult(graph),
|
|
1325
1351
|
isError: false
|
|
1326
1352
|
};
|
|
1327
1353
|
} catch (err) {
|
|
@@ -1364,7 +1390,7 @@ async function createProxy() {
|
|
|
1364
1390
|
idempotentHint: true,
|
|
1365
1391
|
openWorldHint: true
|
|
1366
1392
|
}
|
|
1367
|
-
}, async ({ network, address, coldkey, hotkey, netuid, start_timestamp_ms, end_timestamp_ms, start_block, end_block, depth }) => {
|
|
1393
|
+
}, async ({ network, address, coldkey, hotkey, netuid, start_timestamp_ms, end_timestamp_ms, start_block, end_block, depth, include_attachments }) => {
|
|
1368
1394
|
try {
|
|
1369
1395
|
if (!remoteConnected) return {
|
|
1370
1396
|
content: [{
|
|
@@ -1373,9 +1399,7 @@ async function createProxy() {
|
|
|
1373
1399
|
}],
|
|
1374
1400
|
isError: true
|
|
1375
1401
|
};
|
|
1376
|
-
const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-
|
|
1377
|
-
const { writeGraphReport } = await Promise.resolve().then(() => require("./graph-reports-B3mkLP8Z.cjs"));
|
|
1378
|
-
const { ensureArtifactServer } = await Promise.resolve().then(() => require("./artifact-server-XbN16DwU.cjs"));
|
|
1402
|
+
const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
|
|
1379
1403
|
const result = await stakeInsights(remoteClient, {
|
|
1380
1404
|
network,
|
|
1381
1405
|
address,
|
|
@@ -1389,21 +1413,14 @@ async function createProxy() {
|
|
|
1389
1413
|
depth
|
|
1390
1414
|
});
|
|
1391
1415
|
const subject = address ?? coldkey ?? hotkey ?? "subject";
|
|
1392
|
-
const
|
|
1393
|
-
serverPort: config.serverPort,
|
|
1394
|
-
slug: `stake-insights-${network}-${subject}`
|
|
1395
|
-
});
|
|
1396
|
-
await ensureArtifactServer(config.serverPort);
|
|
1416
|
+
const graph = await writeLocalGraphMeta(result.graphData, config, `stake-insights-${network}-${subject}`, shouldIncludeAttachments({ include_attachments }, workspaceArtifactsEnabled));
|
|
1397
1417
|
return {
|
|
1398
1418
|
content: [{
|
|
1399
1419
|
type: "text",
|
|
1400
1420
|
text: result.summaryText
|
|
1401
1421
|
}],
|
|
1402
1422
|
structuredContent: result.structuredContent,
|
|
1403
|
-
_meta:
|
|
1404
|
-
schema: report.schema,
|
|
1405
|
-
url: report.url
|
|
1406
|
-
} } },
|
|
1423
|
+
_meta: graphMetaResult(graph),
|
|
1407
1424
|
isError: false
|
|
1408
1425
|
};
|
|
1409
1426
|
} catch (err) {
|
|
@@ -1429,7 +1446,7 @@ async function createProxy() {
|
|
|
1429
1446
|
}, async () => ({
|
|
1430
1447
|
content: [{
|
|
1431
1448
|
type: "text",
|
|
1432
|
-
text: [
|
|
1449
|
+
text: workspaceArtifactsEnabled ? [
|
|
1433
1450
|
"Chain Insights AML investigation workspace for AI agents. Workspaces are Obsidian-compatible vaults backed by plain local files.",
|
|
1434
1451
|
"",
|
|
1435
1452
|
CHAIN_INSIGHTS_WORKFLOW,
|
|
@@ -1461,6 +1478,22 @@ async function createProxy() {
|
|
|
1461
1478
|
GRAPH_REPORT_HINTS,
|
|
1462
1479
|
"",
|
|
1463
1480
|
GRAPH_SCHEMA_HINTS
|
|
1481
|
+
].join("\n") : [
|
|
1482
|
+
"Chain Insights stateless AML proxy for host applications.",
|
|
1483
|
+
"",
|
|
1484
|
+
"Local workspace, case, evidence, dossier, session, wallet, and graph report attachment tools are disabled in this mode.",
|
|
1485
|
+
"",
|
|
1486
|
+
"Available graph-backed tools:",
|
|
1487
|
+
"- network_capabilities: inspect supported networks, data layers, tool availability, retention windows, and freshness.",
|
|
1488
|
+
"- address_risk: screen a full address for AML risk, behavior, neighborhood, exchange exposure, and optional compare_address connection checks.",
|
|
1489
|
+
"- stake_insights: explain Bittensor staking around one address, coldkey, or hotkey with net stake, movement amounts, counterparties, backend, and query evidence.",
|
|
1490
|
+
"- trace_victim_funds: trace up to five victim/source addresses forward to exchange deposit candidates.",
|
|
1491
|
+
"- trace_deposit_sources: trace backward from suspected deposit/cashout addresses to upstream funders and shared-source convergence.",
|
|
1492
|
+
"- trace_suspect_funds: trace up to five suspected scammer, mule, operator, or laundering-ring addresses forward to cashout topology.",
|
|
1493
|
+
"- graph_query: run read-only GQL/Cypher through the universal graph endpoint. Use USE live_topology, USE archive_topology, or USE facts.",
|
|
1494
|
+
"- graph_query_batch: run related read-only graph-language queries through one paid graph call.",
|
|
1495
|
+
"",
|
|
1496
|
+
GRAPH_SCHEMA_HINTS
|
|
1464
1497
|
].join("\n")
|
|
1465
1498
|
}],
|
|
1466
1499
|
isError: false
|
|
@@ -1492,7 +1525,7 @@ async function createProxy() {
|
|
|
1492
1525
|
arguments: normalizedArgs
|
|
1493
1526
|
};
|
|
1494
1527
|
const requestOptions = remoteToolRequestOptions(tool.name);
|
|
1495
|
-
return await normalizeRemoteToolResult(requestOptions ? await remoteClient.callTool(request, void 0, requestOptions) : await remoteClient.callTool(request), config, tool.name);
|
|
1528
|
+
return await normalizeRemoteToolResult(requestOptions ? await remoteClient.callTool(request, void 0, requestOptions) : await remoteClient.callTool(request), config, tool.name, shouldIncludeAttachments(normalizedArgs, workspaceArtifactsEnabled));
|
|
1496
1529
|
} catch (err) {
|
|
1497
1530
|
if (err instanceof require_client.PaymentRequiredError) return {
|
|
1498
1531
|
content: [{
|
|
@@ -1550,3 +1583,4 @@ if (process.argv[1] && require("url").pathToFileURL(__filename).href.includes(pr
|
|
|
1550
1583
|
});
|
|
1551
1584
|
//#endregion
|
|
1552
1585
|
exports.createProxy = createProxy;
|
|
1586
|
+
exports.resolveMcpProxyMode = resolveMcpProxyMode;
|