@datasynx/agentic-ai-cartography 1.1.0 → 2.0.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 +197 -33
- package/dist/bookmarks-VS56KVCO.js +25 -0
- package/dist/chunk-CJ2PITFA.js +785 -0
- package/dist/chunk-CJ2PITFA.js.map +1 -0
- package/dist/chunk-D6SRSLBF.js +48 -0
- package/dist/{chunk-WJR63RWY.js → chunk-J6FDZ6HZ.js} +11 -2
- package/dist/chunk-J6FDZ6HZ.js.map +1 -0
- package/dist/chunk-UGSNG3QJ.js +49 -0
- package/dist/chunk-UGSNG3QJ.js.map +1 -0
- package/dist/chunk-W7YE6AAH.js +1516 -0
- package/dist/chunk-W7YE6AAH.js.map +1 -0
- package/dist/cli.js +133 -664
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +60115 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +734 -0
- package/dist/index.d.ts +363 -7
- package/dist/index.js +1462 -161
- package/dist/index.js.map +1 -1
- package/dist/mcp-bin.js +33 -0
- package/dist/mcp-bin.js.map +1 -0
- package/dist/onnxruntime_binding-6Q6HXASN.node +0 -0
- package/dist/onnxruntime_binding-EKZT2NRK.node +0 -0
- package/dist/onnxruntime_binding-P6S7V3CI.node +0 -0
- package/dist/onnxruntime_binding-PJNNIIUO.node +0 -0
- package/dist/onnxruntime_binding-UN6SPTQK.node +0 -0
- package/dist/sdk-A6NLO3DJ.js +12294 -0
- package/dist/sdk-A6NLO3DJ.js.map +1 -0
- package/dist/sdk-G5D4WQZ4.js +12293 -0
- package/dist/sdk-G5D4WQZ4.js.map +1 -0
- package/dist/sdk-QSTAREST.js +4869 -0
- package/dist/sdk-QSTAREST.js.map +1 -0
- package/dist/sqlite-vec-EZN67B2V.js +40 -0
- package/dist/sqlite-vec-EZN67B2V.js.map +1 -0
- package/dist/sqlite-vec-UK5YYE5T.js +39 -0
- package/dist/sqlite-vec-UK5YYE5T.js.map +1 -0
- package/dist/transformers.node-BTYUTJK5.js +42884 -0
- package/dist/transformers.node-BTYUTJK5.js.map +1 -0
- package/dist/transformers.node-J6PRTTOX.js +42883 -0
- package/dist/transformers.node-J6PRTTOX.js.map +1 -0
- package/dist/{types-54623ALF.js → types-JG27FR3E.js} +5 -2
- package/dist/types-JG27FR3E.js.map +1 -0
- package/package.json +53 -17
- package/scripts/postinstall.mjs +7 -0
- package/server.json +28 -0
- package/dist/bookmarks-BWNVQGPG.js +0 -14
- package/dist/chunk-QKNYI3SU.js +0 -459
- package/dist/chunk-QKNYI3SU.js.map +0 -1
- package/dist/chunk-WJR63RWY.js.map +0 -1
- /package/dist/{bookmarks-BWNVQGPG.js.map → bookmarks-VS56KVCO.js.map} +0 -0
- /package/dist/{types-54623ALF.js.map → chunk-D6SRSLBF.js.map} +0 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
+
import http from 'node:http';
|
|
5
|
+
import { McpServerConfig, HookCallback } from '@anthropic-ai/claude-agent-sdk';
|
|
6
|
+
|
|
7
|
+
declare const NODE_TYPES: readonly ["host", "database_server", "database", "table", "web_service", "api_endpoint", "cache_server", "message_broker", "queue", "topic", "container", "pod", "k8s_cluster", "config_file", "saas_tool", "unknown"];
|
|
8
|
+
type NodeType = typeof NODE_TYPES[number];
|
|
9
|
+
/**
|
|
10
|
+
* Semantic groupings of node types — the single source of truth shared by the MCP
|
|
11
|
+
* resource layer (services/databases) and the exporters (layer assignment). Each
|
|
12
|
+
* node type belongs to at most one group; anything ungrouped is treated as "other".
|
|
13
|
+
*/
|
|
14
|
+
declare const NODE_TYPE_GROUPS: {
|
|
15
|
+
readonly saas: readonly ["saas_tool"];
|
|
16
|
+
readonly web: readonly ["web_service", "api_endpoint"];
|
|
17
|
+
readonly data: readonly ["database_server", "database", "table", "cache_server"];
|
|
18
|
+
readonly messaging: readonly ["message_broker", "queue", "topic"];
|
|
19
|
+
readonly infra: readonly ["host", "container", "pod", "k8s_cluster"];
|
|
20
|
+
readonly config: readonly ["config_file"];
|
|
21
|
+
};
|
|
22
|
+
declare const EDGE_RELATIONSHIPS: readonly ["connects_to", "reads_from", "writes_to", "calls", "contains", "depends_on"];
|
|
23
|
+
type EdgeRelationship = typeof EDGE_RELATIONSHIPS[number];
|
|
24
|
+
declare const NodeSchema: z.ZodObject<{
|
|
25
|
+
id: z.ZodString;
|
|
26
|
+
type: z.ZodEnum<{
|
|
27
|
+
host: "host";
|
|
28
|
+
database_server: "database_server";
|
|
29
|
+
database: "database";
|
|
30
|
+
table: "table";
|
|
31
|
+
web_service: "web_service";
|
|
32
|
+
api_endpoint: "api_endpoint";
|
|
33
|
+
cache_server: "cache_server";
|
|
34
|
+
message_broker: "message_broker";
|
|
35
|
+
queue: "queue";
|
|
36
|
+
topic: "topic";
|
|
37
|
+
container: "container";
|
|
38
|
+
pod: "pod";
|
|
39
|
+
k8s_cluster: "k8s_cluster";
|
|
40
|
+
config_file: "config_file";
|
|
41
|
+
saas_tool: "saas_tool";
|
|
42
|
+
unknown: "unknown";
|
|
43
|
+
}>;
|
|
44
|
+
name: z.ZodString;
|
|
45
|
+
discoveredVia: z.ZodString;
|
|
46
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
47
|
+
metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
48
|
+
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
49
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
50
|
+
subDomain: z.ZodOptional<z.ZodString>;
|
|
51
|
+
qualityScore: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
type DiscoveryNode = z.infer<typeof NodeSchema>;
|
|
54
|
+
declare const EdgeSchema: z.ZodObject<{
|
|
55
|
+
sourceId: z.ZodString;
|
|
56
|
+
targetId: z.ZodString;
|
|
57
|
+
relationship: z.ZodEnum<{
|
|
58
|
+
connects_to: "connects_to";
|
|
59
|
+
reads_from: "reads_from";
|
|
60
|
+
writes_to: "writes_to";
|
|
61
|
+
calls: "calls";
|
|
62
|
+
contains: "contains";
|
|
63
|
+
depends_on: "depends_on";
|
|
64
|
+
}>;
|
|
65
|
+
evidence: z.ZodString;
|
|
66
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
type DiscoveryEdge = z.infer<typeof EdgeSchema>;
|
|
69
|
+
declare const DataAssetSchema: z.ZodObject<{
|
|
70
|
+
id: z.ZodString;
|
|
71
|
+
name: z.ZodString;
|
|
72
|
+
domain: z.ZodString;
|
|
73
|
+
subDomain: z.ZodOptional<z.ZodString>;
|
|
74
|
+
qualityScore: z.ZodOptional<z.ZodNumber>;
|
|
75
|
+
metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
76
|
+
position: z.ZodObject<{
|
|
77
|
+
q: z.ZodNumber;
|
|
78
|
+
r: z.ZodNumber;
|
|
79
|
+
}, z.core.$strip>;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
type DataAsset = z.infer<typeof DataAssetSchema>;
|
|
82
|
+
declare const ClusterSchema: z.ZodObject<{
|
|
83
|
+
id: z.ZodString;
|
|
84
|
+
label: z.ZodString;
|
|
85
|
+
domain: z.ZodString;
|
|
86
|
+
color: z.ZodString;
|
|
87
|
+
assetIds: z.ZodArray<z.ZodString>;
|
|
88
|
+
centroid: z.ZodObject<{
|
|
89
|
+
x: z.ZodNumber;
|
|
90
|
+
y: z.ZodNumber;
|
|
91
|
+
}, z.core.$strip>;
|
|
92
|
+
}, z.core.$strip>;
|
|
93
|
+
type Cluster = z.infer<typeof ClusterSchema>;
|
|
94
|
+
declare const ConnectionSchema: z.ZodObject<{
|
|
95
|
+
id: z.ZodString;
|
|
96
|
+
sourceAssetId: z.ZodString;
|
|
97
|
+
targetAssetId: z.ZodString;
|
|
98
|
+
type: z.ZodOptional<z.ZodString>;
|
|
99
|
+
}, z.core.$strip>;
|
|
100
|
+
type Connection = z.infer<typeof ConnectionSchema>;
|
|
101
|
+
interface CartographyMapData {
|
|
102
|
+
assets: DataAsset[];
|
|
103
|
+
clusters: Cluster[];
|
|
104
|
+
connections: Connection[];
|
|
105
|
+
meta: {
|
|
106
|
+
exportedAt: string;
|
|
107
|
+
theme: 'light' | 'dark';
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** Navy → medium blue → periwinkle → teal/cyan palette */
|
|
111
|
+
declare const DOMAIN_COLORS: Record<string, string>;
|
|
112
|
+
/** Ordered palette for dynamic domain assignment */
|
|
113
|
+
declare const DOMAIN_PALETTE: readonly ["#1a2e5a", "#1e3a8a", "#1d4ed8", "#2563eb", "#3b82f6", "#6366f1", "#818cf8", "#7c9fc3", "#0e7490", "#0891b2", "#06b6d4", "#22d3ee", "#0d9488", "#14b8a6", "#2dd4bf", "#5eead4"];
|
|
114
|
+
interface NodeRow extends DiscoveryNode {
|
|
115
|
+
sessionId: string;
|
|
116
|
+
discoveredAt: string;
|
|
117
|
+
depth: number;
|
|
118
|
+
pathId?: string;
|
|
119
|
+
}
|
|
120
|
+
interface EdgeRow extends DiscoveryEdge {
|
|
121
|
+
id: string;
|
|
122
|
+
sessionId: string;
|
|
123
|
+
discoveredAt: string;
|
|
124
|
+
pathId?: string;
|
|
125
|
+
}
|
|
126
|
+
interface SessionRow {
|
|
127
|
+
id: string;
|
|
128
|
+
mode: 'discover';
|
|
129
|
+
startedAt: string;
|
|
130
|
+
completedAt?: string;
|
|
131
|
+
config: string;
|
|
132
|
+
}
|
|
133
|
+
interface CartographyConfig {
|
|
134
|
+
maxDepth: number;
|
|
135
|
+
maxTurns: number;
|
|
136
|
+
entryPoints: string[];
|
|
137
|
+
agentModel: string;
|
|
138
|
+
organization?: string;
|
|
139
|
+
outputDir: string;
|
|
140
|
+
dbPath: string;
|
|
141
|
+
verbose: boolean;
|
|
142
|
+
}
|
|
143
|
+
declare function defaultConfig(overrides?: Partial<CartographyConfig>): CartographyConfig;
|
|
144
|
+
|
|
145
|
+
interface ConnectionRow extends Connection {
|
|
146
|
+
sessionId: string;
|
|
147
|
+
createdAt: string;
|
|
148
|
+
}
|
|
149
|
+
/** Aggregate, low-token index of a topology — used for progressive disclosure. */
|
|
150
|
+
interface GraphSummary {
|
|
151
|
+
sessionId: string;
|
|
152
|
+
totals: {
|
|
153
|
+
nodes: number;
|
|
154
|
+
edges: number;
|
|
155
|
+
};
|
|
156
|
+
nodesByType: Record<string, number>;
|
|
157
|
+
nodesByDomain: Record<string, number>;
|
|
158
|
+
edgesByRelationship: Record<string, number>;
|
|
159
|
+
topConnected: Array<{
|
|
160
|
+
id: string;
|
|
161
|
+
name: string;
|
|
162
|
+
type: string;
|
|
163
|
+
degree: number;
|
|
164
|
+
}>;
|
|
165
|
+
}
|
|
166
|
+
/** Result of a recursive dependency traversal. */
|
|
167
|
+
interface TraversalResult {
|
|
168
|
+
root?: NodeRow;
|
|
169
|
+
direction: 'downstream' | 'upstream' | 'both';
|
|
170
|
+
maxDepth: number;
|
|
171
|
+
nodes: Array<NodeRow & {
|
|
172
|
+
depth: number;
|
|
173
|
+
}>;
|
|
174
|
+
edges: EdgeRow[];
|
|
175
|
+
}
|
|
176
|
+
interface EventRow {
|
|
177
|
+
id: string;
|
|
178
|
+
sessionId: string;
|
|
179
|
+
taskId?: string;
|
|
180
|
+
timestamp: string;
|
|
181
|
+
eventType: string;
|
|
182
|
+
process: string;
|
|
183
|
+
pid: number;
|
|
184
|
+
target?: string;
|
|
185
|
+
targetType?: string;
|
|
186
|
+
port?: number;
|
|
187
|
+
durationMs?: number;
|
|
188
|
+
}
|
|
189
|
+
interface TaskRow {
|
|
190
|
+
id: string;
|
|
191
|
+
sessionId: string;
|
|
192
|
+
description?: string;
|
|
193
|
+
startedAt: string;
|
|
194
|
+
completedAt?: string;
|
|
195
|
+
steps: string;
|
|
196
|
+
involvedServices: string;
|
|
197
|
+
status: 'active' | 'completed' | 'cancelled';
|
|
198
|
+
}
|
|
199
|
+
interface WorkflowRow {
|
|
200
|
+
id: string;
|
|
201
|
+
sessionId: string;
|
|
202
|
+
name?: string;
|
|
203
|
+
pattern: string;
|
|
204
|
+
taskIds: string;
|
|
205
|
+
occurrences: number;
|
|
206
|
+
firstSeen: string;
|
|
207
|
+
lastSeen: string;
|
|
208
|
+
avgDurationMs: number;
|
|
209
|
+
involvedServices: string;
|
|
210
|
+
}
|
|
211
|
+
declare class CartographyDB {
|
|
212
|
+
private db;
|
|
213
|
+
constructor(dbPath: string);
|
|
214
|
+
private migrate;
|
|
215
|
+
close(): void;
|
|
216
|
+
/**
|
|
217
|
+
* Advanced: the underlying better-sqlite3 connection. Used by the optional
|
|
218
|
+
* semantic-search layer to load the `sqlite-vec` extension and manage its
|
|
219
|
+
* virtual table. Prefer the typed methods above for everything else.
|
|
220
|
+
*/
|
|
221
|
+
rawConnection(): Database.Database;
|
|
222
|
+
createSession(mode: 'discover', config: CartographyConfig): string;
|
|
223
|
+
endSession(id: string): void;
|
|
224
|
+
getSession(id: string): SessionRow | undefined;
|
|
225
|
+
getLatestSession(mode?: string): SessionRow | undefined;
|
|
226
|
+
getSessions(): SessionRow[];
|
|
227
|
+
private mapSession;
|
|
228
|
+
upsertNode(sessionId: string, node: DiscoveryNode, depth?: number): void;
|
|
229
|
+
getNodes(sessionId: string, opts?: {
|
|
230
|
+
limit?: number;
|
|
231
|
+
offset?: number;
|
|
232
|
+
}): NodeRow[];
|
|
233
|
+
getNodeCount(sessionId: string): number;
|
|
234
|
+
private mapNode;
|
|
235
|
+
deleteNode(sessionId: string, nodeId: string): void;
|
|
236
|
+
insertEdge(sessionId: string, edge: DiscoveryEdge): void;
|
|
237
|
+
getEdges(sessionId: string, opts?: {
|
|
238
|
+
limit?: number;
|
|
239
|
+
offset?: number;
|
|
240
|
+
}): EdgeRow[];
|
|
241
|
+
insertEvent(sessionId: string, event: Pick<EventRow, 'eventType' | 'process' | 'pid' | 'target' | 'targetType' | 'port'>, taskId?: string): void;
|
|
242
|
+
getEvents(sessionId: string, since?: string): EventRow[];
|
|
243
|
+
startTask(sessionId: string, description?: string): string;
|
|
244
|
+
endCurrentTask(sessionId: string): void;
|
|
245
|
+
updateTaskDescription(sessionId: string, description: string): void;
|
|
246
|
+
getActiveTask(sessionId: string): TaskRow | undefined;
|
|
247
|
+
getTasks(sessionId: string): TaskRow[];
|
|
248
|
+
private mapTask;
|
|
249
|
+
insertWorkflow(sessionId: string, data: Omit<WorkflowRow, 'id'>): void;
|
|
250
|
+
getWorkflows(sessionId: string): WorkflowRow[];
|
|
251
|
+
upsertConnection(sessionId: string, conn: Omit<Connection, 'id'>): string;
|
|
252
|
+
getConnections(sessionId: string): ConnectionRow[];
|
|
253
|
+
deleteConnection(sessionId: string, connectionId: string): void;
|
|
254
|
+
setApproval(pattern: string, action: 'save' | 'ignore' | 'auto'): void;
|
|
255
|
+
getApproval(pattern: string): string | undefined;
|
|
256
|
+
/**
|
|
257
|
+
* Delete a session and all its associated data (nodes, edges, events, tasks, workflows, connections).
|
|
258
|
+
*/
|
|
259
|
+
deleteSession(sessionId: string): void;
|
|
260
|
+
/**
|
|
261
|
+
* Prune sessions older than the given ISO date string. Returns count of deleted sessions.
|
|
262
|
+
*/
|
|
263
|
+
pruneSessions(olderThan: string): number;
|
|
264
|
+
/** Fetch a single node by id within a session. */
|
|
265
|
+
getNode(sessionId: string, nodeId: string): NodeRow | undefined;
|
|
266
|
+
/** Batch-fetch nodes by id, keyed for O(1) lookup. Chunked to stay under SQLite's bind-variable limit. */
|
|
267
|
+
getNodesByIds(sessionId: string, ids: readonly string[]): Map<string, NodeRow>;
|
|
268
|
+
/** Fetch all nodes of one or more types. */
|
|
269
|
+
getNodesByType(sessionId: string, types: readonly string[]): NodeRow[];
|
|
270
|
+
/**
|
|
271
|
+
* Lexical search over node id, name, domain, sub-domain and tags.
|
|
272
|
+
* Case-insensitive substring match — the deterministic fallback for semantic search.
|
|
273
|
+
*/
|
|
274
|
+
searchNodes(sessionId: string, query: string, opts?: {
|
|
275
|
+
types?: readonly string[];
|
|
276
|
+
limit?: number;
|
|
277
|
+
}): NodeRow[];
|
|
278
|
+
/**
|
|
279
|
+
* Traverse the dependency graph from a node using a recursive CTE with a
|
|
280
|
+
* path-based cycle guard. `downstream` follows source→target (what the node
|
|
281
|
+
* depends on / points to); `upstream` follows target→source (what depends on it).
|
|
282
|
+
*/
|
|
283
|
+
getDependencies(sessionId: string, nodeId: string, opts?: {
|
|
284
|
+
direction?: 'downstream' | 'upstream' | 'both';
|
|
285
|
+
maxDepth?: number;
|
|
286
|
+
}): TraversalResult;
|
|
287
|
+
/** Lightweight aggregate index of the whole topology — the progressive-disclosure summary. */
|
|
288
|
+
getGraphSummary(sessionId: string): GraphSummary;
|
|
289
|
+
getStats(sessionId: string): {
|
|
290
|
+
nodes: number;
|
|
291
|
+
edges: number;
|
|
292
|
+
events: number;
|
|
293
|
+
tasks: number;
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* The Cartography MCP server — the package's primary, LLM-agnostic interface.
|
|
299
|
+
*
|
|
300
|
+
* It exposes the discovered infrastructure topology as Model Context Protocol
|
|
301
|
+
* **Resources** (read-only context, progressive disclosure), a small set of query
|
|
302
|
+
* **Tools** (parameterized lookups), and reusable **Prompts**. Any MCP host —
|
|
303
|
+
* Claude Code, Cursor, Cline, Windsurf, the Vercel AI SDK, LangGraph — can drive
|
|
304
|
+
* it; the package never needs to know which model is in use.
|
|
305
|
+
*/
|
|
306
|
+
|
|
307
|
+
/** A pluggable search backend; defaults to lexical search, can be upgraded to semantic. */
|
|
308
|
+
type SearchFn = (db: CartographyDB, sessionId: string, query: string, opts: {
|
|
309
|
+
types?: readonly string[];
|
|
310
|
+
limit: number;
|
|
311
|
+
}) => Promise<Array<{
|
|
312
|
+
node: NodeRow;
|
|
313
|
+
score?: number;
|
|
314
|
+
}>>;
|
|
315
|
+
/** A pluggable discovery backend invoked by the `run_discovery` tool. */
|
|
316
|
+
type DiscoveryFn = (db: CartographyDB, sessionId: string, opts: {
|
|
317
|
+
hint?: string;
|
|
318
|
+
}) => Promise<{
|
|
319
|
+
nodes: number;
|
|
320
|
+
edges: number;
|
|
321
|
+
}>;
|
|
322
|
+
interface CreateMcpServerOptions {
|
|
323
|
+
/** Database instance. If omitted, one is opened at `config.dbPath`. */
|
|
324
|
+
db?: CartographyDB;
|
|
325
|
+
/** Path to the SQLite catalog (used when `db` is not provided). */
|
|
326
|
+
dbPath?: string;
|
|
327
|
+
/** Session to serve: a session id, or `'latest'` (default) for the newest discovery. */
|
|
328
|
+
session?: string | 'latest';
|
|
329
|
+
/** Semantic/lexical search backend. Defaults to lexical `searchNodes`. */
|
|
330
|
+
search?: SearchFn;
|
|
331
|
+
/** Discovery backend for `run_discovery`/`refresh`. Optional. */
|
|
332
|
+
discovery?: DiscoveryFn;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Build a fully-configured Cartography MCP server. Call `.connect(transport)` to run it.
|
|
336
|
+
*/
|
|
337
|
+
declare function createMcpServer(opts?: CreateMcpServerOptions): McpServer;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Transport bindings for the Cartography MCP server.
|
|
341
|
+
*
|
|
342
|
+
* - **stdio**: the local-first default — zero network, every client supports it.
|
|
343
|
+
* - **Streamable HTTP**: a single `/mcp` endpoint for team/remote use, bound to
|
|
344
|
+
* localhost with DNS-rebinding protection. The deprecated SSE transport is not used.
|
|
345
|
+
*/
|
|
346
|
+
|
|
347
|
+
/** Connect a server over stdio (resolves when the transport closes). */
|
|
348
|
+
declare function runStdio(server: McpServer): Promise<void>;
|
|
349
|
+
interface HttpOptions {
|
|
350
|
+
port?: number;
|
|
351
|
+
host?: string;
|
|
352
|
+
/** Extra allowed Host headers (defaults to localhost:port variants). */
|
|
353
|
+
allowedHosts?: string[];
|
|
354
|
+
/** Allowed Origin headers (defaults to none → same-origin only). */
|
|
355
|
+
allowedOrigins?: string[];
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Start a Streamable HTTP server. A fresh MCP server instance is created per
|
|
359
|
+
* session via `factory`, so multiple clients can connect concurrently.
|
|
360
|
+
*/
|
|
361
|
+
declare function runHttp(factory: () => McpServer, opts?: HttpOptions): Promise<http.Server>;
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Cross-platform utilities for Linux, macOS, and Windows.
|
|
365
|
+
* Centralizes all OS-specific logic so scanning tools work everywhere.
|
|
366
|
+
*/
|
|
367
|
+
type Platform = 'linux' | 'darwin' | 'win32';
|
|
368
|
+
declare function safeEnv(): NodeJS.ProcessEnv;
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Scanner plugin contract.
|
|
372
|
+
*
|
|
373
|
+
* A scanner detects whether it applies to the current machine, then produces a
|
|
374
|
+
* read-only {@link ScanResult}: deterministic nodes/edges where the data is
|
|
375
|
+
* structured enough, plus an optional raw report for an LLM to classify further.
|
|
376
|
+
*
|
|
377
|
+
* Modeled on Steampipe plugins / Backstage processors: new sources can be added
|
|
378
|
+
* (in-tree or via `@datasynx/scanner-*` packages) and registered without forking
|
|
379
|
+
* the core. Each scanner declares the commands it needs, feeding the safety layer.
|
|
380
|
+
*/
|
|
381
|
+
|
|
382
|
+
interface ScanContext {
|
|
383
|
+
/** Optional focus hint from the caller (e.g. tool names to look for). */
|
|
384
|
+
hint?: string;
|
|
385
|
+
/** The current platform. */
|
|
386
|
+
platform: Platform;
|
|
387
|
+
/** Allowlist-gated command runner (returns '' on error/blocked). */
|
|
388
|
+
run: (cmd: string, opts?: {
|
|
389
|
+
timeout?: number;
|
|
390
|
+
env?: NodeJS.ProcessEnv;
|
|
391
|
+
}) => string;
|
|
392
|
+
}
|
|
393
|
+
interface ScanResult {
|
|
394
|
+
/** Deterministically classified nodes. */
|
|
395
|
+
nodes: DiscoveryNode[];
|
|
396
|
+
/** Deterministically classified edges. */
|
|
397
|
+
edges: DiscoveryEdge[];
|
|
398
|
+
/** Optional raw text report for LLM-driven classification. */
|
|
399
|
+
report?: string;
|
|
400
|
+
}
|
|
401
|
+
interface Scanner {
|
|
402
|
+
/** Stable id, e.g. "bookmarks", "installed-apps", "cloud-aws". */
|
|
403
|
+
id: string;
|
|
404
|
+
/** Human-readable title. */
|
|
405
|
+
title: string;
|
|
406
|
+
/** Platforms this scanner supports, or 'all'. */
|
|
407
|
+
platforms: Platform[] | 'all';
|
|
408
|
+
/** Read-only commands this scanner may run (declared for the safety layer/docs). */
|
|
409
|
+
allowedCommands?: string[];
|
|
410
|
+
/** Cheap check whether the scanner applies here (e.g. a CLI is installed). */
|
|
411
|
+
detect(ctx: ScanContext): boolean | Promise<boolean>;
|
|
412
|
+
/** Perform the read-only scan. */
|
|
413
|
+
scan(ctx: ScanContext): Promise<ScanResult>;
|
|
414
|
+
}
|
|
415
|
+
/** A typed registry of scanners with lazy, platform-aware selection. */
|
|
416
|
+
declare class ScannerRegistry {
|
|
417
|
+
private scanners;
|
|
418
|
+
register(scanner: Scanner): this;
|
|
419
|
+
get(id: string): Scanner | undefined;
|
|
420
|
+
list(): Scanner[];
|
|
421
|
+
/** Scanners whose `platforms` include the given platform. */
|
|
422
|
+
forPlatform(platform: Platform): Scanner[];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
declare const bookmarksScanner: Scanner;
|
|
426
|
+
|
|
427
|
+
declare const installedAppsScanner: Scanner;
|
|
428
|
+
|
|
429
|
+
/** Extract distinct listening port numbers from ss/lsof/PowerShell output. */
|
|
430
|
+
declare function extractListeningPorts(raw: string): number[];
|
|
431
|
+
declare const portsScanner: Scanner;
|
|
432
|
+
|
|
433
|
+
/** A registry pre-loaded with the built-in deterministic scanners. */
|
|
434
|
+
declare function defaultRegistry(): ScannerRegistry;
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Deterministic, LLM-free local discovery.
|
|
438
|
+
*
|
|
439
|
+
* Runs every applicable scanner from a {@link ScannerRegistry}, deduplicates and
|
|
440
|
+
* persists the resulting nodes/edges, and returns counts. This is what powers the
|
|
441
|
+
* MCP `run_discovery` tool without requiring any model — the host LLM can then
|
|
442
|
+
* enrich the catalog via the read tools. (The Claude-driven loop in agent.ts
|
|
443
|
+
* remains available as the optional, richer turnkey path.)
|
|
444
|
+
*/
|
|
445
|
+
|
|
446
|
+
interface LocalDiscoveryOptions {
|
|
447
|
+
hint?: string;
|
|
448
|
+
registry?: ScannerRegistry;
|
|
449
|
+
/** Called after each scanner with a short progress line. */
|
|
450
|
+
onProgress?: (line: string) => void;
|
|
451
|
+
}
|
|
452
|
+
declare function runLocalDiscovery(db: CartographyDB, sessionId: string, opts?: LocalDiscoveryOptions): Promise<{
|
|
453
|
+
nodes: number;
|
|
454
|
+
edges: number;
|
|
455
|
+
scanners: string[];
|
|
456
|
+
}>;
|
|
457
|
+
/** Adapter matching the MCP `DiscoveryFn` signature. */
|
|
458
|
+
declare function localDiscoveryFn(registry?: ScannerRegistry): (db: CartographyDB, sessionId: string, opts: {
|
|
459
|
+
hint?: string;
|
|
460
|
+
}) => Promise<{
|
|
461
|
+
nodes: number;
|
|
462
|
+
edges: number;
|
|
463
|
+
}>;
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Embedding providers for semantic search.
|
|
467
|
+
*
|
|
468
|
+
* The default provider runs a small sentence-transformer locally via
|
|
469
|
+
* `@huggingface/transformers` (no API key, offline after first download), keeping
|
|
470
|
+
* the package LLM-agnostic. Everything is a lazy import so installs that never use
|
|
471
|
+
* semantic search pay no cost and need no native model.
|
|
472
|
+
*/
|
|
473
|
+
/** Produces fixed-dimension embeddings for a batch of texts. */
|
|
474
|
+
interface EmbeddingProvider {
|
|
475
|
+
readonly id: string;
|
|
476
|
+
readonly dimensions: number;
|
|
477
|
+
embed(texts: string[]): Promise<Float32Array[]>;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Local sentence-transformer embedder (Xenova/all-MiniLM-L6-v2, 384 dims).
|
|
481
|
+
* Returns `undefined` if `@huggingface/transformers` is not installed or the
|
|
482
|
+
* model cannot be loaded, so callers can fall back to lexical search.
|
|
483
|
+
*/
|
|
484
|
+
declare function createLocalEmbedder(model?: string): Promise<EmbeddingProvider | undefined>;
|
|
485
|
+
/**
|
|
486
|
+
* A deterministic, dependency-free hashing embedder (bag-of-character-ngrams).
|
|
487
|
+
* Not as good as a transformer, but offline, instant, and useful as a fallback
|
|
488
|
+
* and for tests. Produces L2-normalized vectors.
|
|
489
|
+
*/
|
|
490
|
+
declare function createHashEmbedder(dimensions?: number): EmbeddingProvider;
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Vector store backed by `sqlite-vec`. Stores one embedding per node in a `vec0`
|
|
494
|
+
* virtual table living inside the same SQLite catalog, with incremental indexing
|
|
495
|
+
* (content-hashed) so re-runs only embed what changed.
|
|
496
|
+
*/
|
|
497
|
+
|
|
498
|
+
declare class VectorStore {
|
|
499
|
+
private db;
|
|
500
|
+
private embedder;
|
|
501
|
+
private loaded;
|
|
502
|
+
constructor(db: CartographyDB, embedder: EmbeddingProvider);
|
|
503
|
+
/** Load sqlite-vec and ensure the schema exists. Returns false if unavailable. */
|
|
504
|
+
init(): Promise<boolean>;
|
|
505
|
+
/** Incrementally embed and index any new/changed nodes for a session. */
|
|
506
|
+
index(sessionId: string): Promise<{
|
|
507
|
+
embedded: number;
|
|
508
|
+
total: number;
|
|
509
|
+
}>;
|
|
510
|
+
/** k-nearest-neighbour search within a session. Returns node ids + distances. */
|
|
511
|
+
search(sessionId: string, query: string, k: number): Promise<Array<{
|
|
512
|
+
nodeId: string;
|
|
513
|
+
distance: number;
|
|
514
|
+
}>>;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Semantic search backend for the MCP server. Wraps a {@link VectorStore} and
|
|
519
|
+
* degrades gracefully to lexical search when embeddings/sqlite-vec are unavailable
|
|
520
|
+
* or return nothing.
|
|
521
|
+
*/
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Build a {@link SearchFn} that prefers semantic (vector) search and falls back to
|
|
525
|
+
* lexical. Pass an explicit embedder, or let it lazily load the local transformer
|
|
526
|
+
* (returns a lexical-only function if none is available).
|
|
527
|
+
*/
|
|
528
|
+
declare function createSemanticSearch(db: CartographyDB, embedder?: EmbeddingProvider): Promise<SearchFn>;
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Circuit breaker for sequential CLI scans.
|
|
532
|
+
* After `threshold` consecutive failures, remaining commands are skipped.
|
|
533
|
+
*/
|
|
534
|
+
declare function createScanRunner(runFn: (cmd: string, opts?: {
|
|
535
|
+
timeout?: number;
|
|
536
|
+
env?: NodeJS.ProcessEnv;
|
|
537
|
+
}) => string, opts?: {
|
|
538
|
+
timeout?: number;
|
|
539
|
+
env?: NodeJS.ProcessEnv;
|
|
540
|
+
threshold?: number;
|
|
541
|
+
}): (cmd: string) => string;
|
|
542
|
+
interface CartographyToolsOptions {
|
|
543
|
+
/** Called when the agent needs a human answer. Return the user's response. */
|
|
544
|
+
onAskUser?: (question: string, context?: string) => Promise<string>;
|
|
545
|
+
}
|
|
546
|
+
declare function stripSensitive(target: string): string;
|
|
547
|
+
declare function createCartographyTools(db: CartographyDB, sessionId: string, opts?: CartographyToolsOptions): Promise<McpServerConfig>;
|
|
548
|
+
|
|
549
|
+
declare const safetyHook: HookCallback;
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Read-only command policy — a strict allowlist.
|
|
553
|
+
*
|
|
554
|
+
* Unlike a denylist (which is inherently leaky — novel destructive commands slip
|
|
555
|
+
* through), this module permits only commands that are known to be read-only and
|
|
556
|
+
* rejects everything else. It is the authoritative safety boundary for every
|
|
557
|
+
* command the package spawns, independent of which agent or LLM is driving.
|
|
558
|
+
*
|
|
559
|
+
* The check is shell-aware: it splits a command line into segments on the control
|
|
560
|
+
* operators `|`, `&&`, `||`, `;` (respecting single/double quotes), then validates
|
|
561
|
+
* the leading executable of each segment plus its sub-command/arguments.
|
|
562
|
+
*/
|
|
563
|
+
interface PolicyResult {
|
|
564
|
+
allowed: boolean;
|
|
565
|
+
reason?: string;
|
|
566
|
+
}
|
|
567
|
+
type ShellKind = 'posix' | 'powershell';
|
|
568
|
+
/** Split a command line on shell control operators, honoring single/double quotes. */
|
|
569
|
+
declare function splitSegments(cmd: string): string[];
|
|
570
|
+
/**
|
|
571
|
+
* Decide whether a command line is read-only and therefore safe to execute.
|
|
572
|
+
* Returns `{ allowed: false, reason }` for anything not explicitly permitted.
|
|
573
|
+
*/
|
|
574
|
+
declare function checkReadOnly(command: string, opts?: {
|
|
575
|
+
shell?: ShellKind;
|
|
576
|
+
}): PolicyResult;
|
|
577
|
+
/** Convenience boolean form. */
|
|
578
|
+
declare function isReadOnlyCommand(command: string): boolean;
|
|
579
|
+
/** Throwing form for guard sites that prefer exceptions. */
|
|
580
|
+
declare function assertReadOnly(command: string): void;
|
|
581
|
+
|
|
582
|
+
type DiscoveryEvent = {
|
|
583
|
+
kind: 'thinking';
|
|
584
|
+
text: string;
|
|
585
|
+
} | {
|
|
586
|
+
kind: 'tool_call';
|
|
587
|
+
tool: string;
|
|
588
|
+
input: Record<string, unknown>;
|
|
589
|
+
} | {
|
|
590
|
+
kind: 'tool_result';
|
|
591
|
+
tool: string;
|
|
592
|
+
output: string;
|
|
593
|
+
} | {
|
|
594
|
+
kind: 'turn';
|
|
595
|
+
turn: number;
|
|
596
|
+
} | {
|
|
597
|
+
kind: 'error';
|
|
598
|
+
text: string;
|
|
599
|
+
} | {
|
|
600
|
+
kind: 'done';
|
|
601
|
+
};
|
|
602
|
+
type AskUserFn = (question: string, context?: string) => Promise<string>;
|
|
603
|
+
declare function runDiscovery(config: CartographyConfig, db: CartographyDB, sessionId: string, onEvent?: (event: DiscoveryEvent) => void, onAskUser?: AskUserFn, hint?: string): Promise<void>;
|
|
604
|
+
|
|
605
|
+
declare function generateTopologyMermaid(nodes: NodeRow[], edges: EdgeRow[]): string;
|
|
606
|
+
declare function generateDependencyMermaid(nodes: NodeRow[], edges: EdgeRow[]): string;
|
|
607
|
+
declare function exportBackstageYAML(nodes: NodeRow[], edges: EdgeRow[], org?: string): string;
|
|
608
|
+
declare function exportJSON(db: CartographyDB, sessionId: string): string;
|
|
609
|
+
declare function exportDiscoveryApp(nodes: NodeRow[], edges: EdgeRow[], options?: {
|
|
610
|
+
theme?: 'light' | 'dark';
|
|
611
|
+
}): string;
|
|
612
|
+
declare function exportJGF(nodes: NodeRow[], edges: EdgeRow[]): string;
|
|
613
|
+
declare function exportAll(db: CartographyDB, sessionId: string, outputDir: string, formats?: string[]): void;
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Hex Grid Engine — flat-top axial coordinate system.
|
|
617
|
+
* Reference: https://www.redblobgames.com/grids/hexagons/
|
|
618
|
+
*/
|
|
619
|
+
interface AxialCoord {
|
|
620
|
+
q: number;
|
|
621
|
+
r: number;
|
|
622
|
+
}
|
|
623
|
+
interface PixelCoord {
|
|
624
|
+
x: number;
|
|
625
|
+
y: number;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Convert axial hex coordinates to pixel coordinates (flat-top).
|
|
629
|
+
*/
|
|
630
|
+
declare function hexToPixel(q: number, r: number, size: number): PixelCoord;
|
|
631
|
+
/**
|
|
632
|
+
* Convert pixel coordinates to nearest axial hex (flat-top).
|
|
633
|
+
*/
|
|
634
|
+
declare function pixelToHex(x: number, y: number, size: number): AxialCoord;
|
|
635
|
+
/**
|
|
636
|
+
* Return the 6 pixel corners of a flat-top hexagon.
|
|
637
|
+
*/
|
|
638
|
+
declare function hexCorners(cx: number, cy: number, size: number): PixelCoord[];
|
|
639
|
+
declare function hexNeighbors(q: number, r: number): AxialCoord[];
|
|
640
|
+
declare function hexDistance(a: AxialCoord, b: AxialCoord): number;
|
|
641
|
+
/**
|
|
642
|
+
* Generate all hex coordinates on a given ring around center.
|
|
643
|
+
*/
|
|
644
|
+
declare function hexRing(center: AxialCoord, radius: number): AxialCoord[];
|
|
645
|
+
/**
|
|
646
|
+
* Generate a spiral sequence of hex positions (ring 0, ring 1, ring 2, …).
|
|
647
|
+
* Returns exactly `count` positions.
|
|
648
|
+
*/
|
|
649
|
+
declare function hexSpiral(center: AxialCoord, count: number): AxialCoord[];
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Domain-based clustering and hex grid positioning.
|
|
653
|
+
* Groups data assets by domain, assigns organic hex positions via spiral fill,
|
|
654
|
+
* computes cluster centroids and assigns colors from the domain palette.
|
|
655
|
+
*/
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Assign colors to all domains in the dataset.
|
|
659
|
+
*/
|
|
660
|
+
declare function assignColors(domains: string[]): Record<string, string>;
|
|
661
|
+
/**
|
|
662
|
+
* Generate a slightly lighter shade of a hex color string.
|
|
663
|
+
*/
|
|
664
|
+
declare function shadeVariant(hex: string, amount: number): string;
|
|
665
|
+
/**
|
|
666
|
+
* Group assets by their `domain` field.
|
|
667
|
+
*/
|
|
668
|
+
declare function groupByDomain(assets: DataAsset[]): Map<string, DataAsset[]>;
|
|
669
|
+
/**
|
|
670
|
+
* Arrange domain clusters on the hex grid without overlap.
|
|
671
|
+
* Places largest clusters first at the origin, subsequent clusters spiral outward.
|
|
672
|
+
*/
|
|
673
|
+
declare function layoutClusters(groups: Map<string, DataAsset[]>, hexSize: number): {
|
|
674
|
+
clusters: Cluster[];
|
|
675
|
+
assets: DataAsset[];
|
|
676
|
+
};
|
|
677
|
+
declare function computeCentroid(positions: AxialCoord[], hexSize: number): {
|
|
678
|
+
x: number;
|
|
679
|
+
y: number;
|
|
680
|
+
};
|
|
681
|
+
declare function computeClusterBounds(assets: DataAsset[], hexSize: number): {
|
|
682
|
+
minX: number;
|
|
683
|
+
minY: number;
|
|
684
|
+
maxX: number;
|
|
685
|
+
maxY: number;
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Node-to-Asset Mapping.
|
|
690
|
+
* Converts existing DiscoveryNode/Edge data into the CartographyMap data model.
|
|
691
|
+
*/
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Convert NodeRow[] to DataAsset[].
|
|
695
|
+
*/
|
|
696
|
+
declare function nodesToAssets(nodes: NodeRow[]): DataAsset[];
|
|
697
|
+
/**
|
|
698
|
+
* Convert EdgeRow[] to Connection[].
|
|
699
|
+
*/
|
|
700
|
+
declare function edgesToConnections(edges: EdgeRow[]): Connection[];
|
|
701
|
+
/**
|
|
702
|
+
* Build a complete CartographyMapData from raw nodes and edges.
|
|
703
|
+
*/
|
|
704
|
+
declare function buildMapData(nodes: NodeRow[], edges: EdgeRow[], options?: {
|
|
705
|
+
theme?: 'light' | 'dark';
|
|
706
|
+
}): CartographyMapData;
|
|
707
|
+
|
|
708
|
+
declare function checkPrerequisites(): void;
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Remove orphaned temp files from previous bookmark/history scans.
|
|
712
|
+
* Call at startup to prevent /tmp accumulation after crashes.
|
|
713
|
+
*/
|
|
714
|
+
declare function cleanupTempFiles(): number;
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Structured logging for enterprise observability.
|
|
718
|
+
* Outputs JSON to stderr for compatibility with ELK, Datadog, Splunk, CloudWatch.
|
|
719
|
+
*/
|
|
720
|
+
type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
|
|
721
|
+
interface LogEntry {
|
|
722
|
+
timestamp: string;
|
|
723
|
+
level: LogLevel;
|
|
724
|
+
message: string;
|
|
725
|
+
context?: Record<string, unknown>;
|
|
726
|
+
}
|
|
727
|
+
declare function setVerbose(v: boolean): void;
|
|
728
|
+
declare function log(level: LogLevel, message: string, context?: Record<string, unknown>): void;
|
|
729
|
+
declare function logDebug(message: string, context?: Record<string, unknown>): void;
|
|
730
|
+
declare function logInfo(message: string, context?: Record<string, unknown>): void;
|
|
731
|
+
declare function logWarn(message: string, context?: Record<string, unknown>): void;
|
|
732
|
+
declare function logError(message: string, context?: Record<string, unknown>): void;
|
|
733
|
+
|
|
734
|
+
export { type CartographyConfig, CartographyDB, type CartographyMapData, type Cluster, ClusterSchema, type Connection, ConnectionSchema, type CreateMcpServerOptions, DOMAIN_COLORS, DOMAIN_PALETTE, type DataAsset, DataAssetSchema, type DiscoveryEdge, type DiscoveryEvent, type DiscoveryFn, type DiscoveryNode, EDGE_RELATIONSHIPS, type EdgeRelationship, type EdgeRow, EdgeSchema, type EmbeddingProvider, type GraphSummary, type HttpOptions, type LocalDiscoveryOptions, type LogEntry, type LogLevel, NODE_TYPES, NODE_TYPE_GROUPS, type NodeRow, NodeSchema, type NodeType, type PolicyResult, type ScanContext, type ScanResult, type Scanner, ScannerRegistry, type SearchFn, type SessionRow, type ShellKind, type TraversalResult, VectorStore, assertReadOnly, assignColors, bookmarksScanner, buildMapData, checkPrerequisites, checkReadOnly, cleanupTempFiles, computeCentroid, computeClusterBounds, createCartographyTools, createHashEmbedder, createLocalEmbedder, createMcpServer, createScanRunner, createSemanticSearch, defaultConfig, defaultRegistry, edgesToConnections, exportAll, exportBackstageYAML, exportDiscoveryApp, exportJGF, exportJSON, extractListeningPorts, generateDependencyMermaid, generateTopologyMermaid, groupByDomain, hexCorners, hexDistance, hexNeighbors, hexRing, hexSpiral, hexToPixel, installedAppsScanner, isReadOnlyCommand, layoutClusters, localDiscoveryFn, log, logDebug, logError, logInfo, logWarn, nodesToAssets, pixelToHex, portsScanner, runDiscovery, runHttp, runLocalDiscovery, runStdio, safeEnv, safetyHook, setVerbose, shadeVariant, splitSegments, stripSensitive };
|