@datasynx/agentic-ai-cartography 1.1.1 → 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.
Files changed (50) hide show
  1. package/README.md +197 -33
  2. package/dist/bookmarks-VS56KVCO.js +25 -0
  3. package/dist/chunk-CJ2PITFA.js +785 -0
  4. package/dist/chunk-CJ2PITFA.js.map +1 -0
  5. package/dist/chunk-D6SRSLBF.js +48 -0
  6. package/dist/{chunk-WJR63RWY.js → chunk-J6FDZ6HZ.js} +11 -2
  7. package/dist/chunk-J6FDZ6HZ.js.map +1 -0
  8. package/dist/chunk-UGSNG3QJ.js +49 -0
  9. package/dist/chunk-UGSNG3QJ.js.map +1 -0
  10. package/dist/chunk-W7YE6AAH.js +1516 -0
  11. package/dist/chunk-W7YE6AAH.js.map +1 -0
  12. package/dist/cli.js +133 -664
  13. package/dist/cli.js.map +1 -1
  14. package/dist/index.cjs +60115 -0
  15. package/dist/index.cjs.map +1 -0
  16. package/dist/index.d.cts +734 -0
  17. package/dist/index.d.ts +363 -7
  18. package/dist/index.js +1462 -161
  19. package/dist/index.js.map +1 -1
  20. package/dist/mcp-bin.js +33 -0
  21. package/dist/mcp-bin.js.map +1 -0
  22. package/dist/onnxruntime_binding-6Q6HXASN.node +0 -0
  23. package/dist/onnxruntime_binding-EKZT2NRK.node +0 -0
  24. package/dist/onnxruntime_binding-P6S7V3CI.node +0 -0
  25. package/dist/onnxruntime_binding-PJNNIIUO.node +0 -0
  26. package/dist/onnxruntime_binding-UN6SPTQK.node +0 -0
  27. package/dist/sdk-A6NLO3DJ.js +12294 -0
  28. package/dist/sdk-A6NLO3DJ.js.map +1 -0
  29. package/dist/sdk-G5D4WQZ4.js +12293 -0
  30. package/dist/sdk-G5D4WQZ4.js.map +1 -0
  31. package/dist/sdk-QSTAREST.js +4869 -0
  32. package/dist/sdk-QSTAREST.js.map +1 -0
  33. package/dist/sqlite-vec-EZN67B2V.js +40 -0
  34. package/dist/sqlite-vec-EZN67B2V.js.map +1 -0
  35. package/dist/sqlite-vec-UK5YYE5T.js +39 -0
  36. package/dist/sqlite-vec-UK5YYE5T.js.map +1 -0
  37. package/dist/transformers.node-BTYUTJK5.js +42884 -0
  38. package/dist/transformers.node-BTYUTJK5.js.map +1 -0
  39. package/dist/transformers.node-J6PRTTOX.js +42883 -0
  40. package/dist/transformers.node-J6PRTTOX.js.map +1 -0
  41. package/dist/{types-54623ALF.js → types-JG27FR3E.js} +5 -2
  42. package/dist/types-JG27FR3E.js.map +1 -0
  43. package/package.json +51 -16
  44. package/server.json +28 -0
  45. package/dist/bookmarks-BWNVQGPG.js +0 -14
  46. package/dist/chunk-QKNYI3SU.js +0 -459
  47. package/dist/chunk-QKNYI3SU.js.map +0 -1
  48. package/dist/chunk-WJR63RWY.js.map +0 -1
  49. /package/dist/{bookmarks-BWNVQGPG.js.map → bookmarks-VS56KVCO.js.map} +0 -0
  50. /package/dist/{types-54623ALF.js.map → chunk-D6SRSLBF.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db.ts","../src/mcp/server.ts","../src/mcp/transports.ts","../src/semantic/hash.ts","../src/semantic/embeddings.ts","../src/semantic/store.ts","../src/semantic/search.ts","../src/scanners/types.ts","../src/scanners/bookmarks.ts","../src/scanners/installed-apps.ts","../src/scanners/ports.ts","../src/scanners/registry.ts","../src/discovery/local.ts","../src/mcp/start.ts"],"sourcesContent":["import Database from 'better-sqlite3';\nimport { mkdirSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { z } from 'zod';\nimport { NODE_TYPES, EDGE_RELATIONSHIPS } from './types.js';\nimport type {\n CartographyConfig, DiscoveryNode, DiscoveryEdge,\n NodeRow, EdgeRow, SessionRow, Connection,\n} from './types.js';\n\n// ── Row validation schemas ──────────────────────────────────────────────────\n\nconst SessionRowSchema = z.object({\n id: z.string(),\n mode: z.literal('discover'),\n started_at: z.string(),\n completed_at: z.string().nullable().optional(),\n config: z.string(),\n});\n\nconst NodeRowSchema = z.object({\n id: z.string(),\n session_id: z.string(),\n type: z.enum(NODE_TYPES),\n name: z.string(),\n discovered_via: z.string().nullable().optional(),\n discovered_at: z.string(),\n path_id: z.string().nullable().optional(),\n depth: z.number().default(0),\n confidence: z.number().default(0.5),\n metadata: z.string().default('{}'),\n tags: z.string().default('[]'),\n domain: z.string().nullable().optional(),\n sub_domain: z.string().nullable().optional(),\n quality_score: z.number().nullable().optional(),\n});\n\nconst EdgeRowSchema = z.object({\n id: z.string(),\n session_id: z.string(),\n source_id: z.string(),\n target_id: z.string(),\n relationship: z.enum(EDGE_RELATIONSHIPS),\n evidence: z.string().nullable().optional(),\n confidence: z.number().default(0.5),\n discovered_at: z.string(),\n});\n\nconst EventRowSchema = z.object({\n id: z.string(),\n session_id: z.string(),\n task_id: z.string().nullable().optional(),\n timestamp: z.string(),\n event_type: z.string(),\n process: z.string(),\n pid: z.number(),\n target: z.string().nullable().optional(),\n target_type: z.string().nullable().optional(),\n port: z.number().nullable().optional(),\n duration_ms: z.number().nullable().optional(),\n});\n\nconst TaskRowSchema = z.object({\n id: z.string(),\n session_id: z.string(),\n description: z.string().nullable().optional(),\n started_at: z.string(),\n completed_at: z.string().nullable().optional(),\n steps: z.string().default('[]'),\n involved_services: z.string().default('[]'),\n status: z.enum(['active', 'completed', 'cancelled']),\n});\n\nconst WorkflowRowSchema = z.object({\n id: z.string(),\n session_id: z.string(),\n name: z.string().nullable().optional(),\n pattern: z.string(),\n task_ids: z.string().default('[]'),\n occurrences: z.number().default(1),\n first_seen: z.string(),\n last_seen: z.string(),\n avg_duration_ms: z.number().nullable().optional(),\n involved_services: z.string().default('[]'),\n});\n\nconst ConnectionRowSchema = z.object({\n id: z.string(),\n session_id: z.string(),\n source_asset_id: z.string(),\n target_asset_id: z.string(),\n type: z.string().nullable().optional(),\n created_at: z.string(),\n});\n\nexport interface ConnectionRow extends Connection {\n sessionId: string;\n createdAt: string;\n}\n\n/** Aggregate, low-token index of a topology — used for progressive disclosure. */\nexport interface GraphSummary {\n sessionId: string;\n totals: { nodes: number; edges: number };\n nodesByType: Record<string, number>;\n nodesByDomain: Record<string, number>;\n edgesByRelationship: Record<string, number>;\n topConnected: Array<{ id: string; name: string; type: string; degree: number }>;\n}\n\n/** Result of a recursive dependency traversal. */\nexport interface TraversalResult {\n root?: NodeRow;\n direction: 'downstream' | 'upstream' | 'both';\n maxDepth: number;\n nodes: Array<NodeRow & { depth: number }>;\n edges: EdgeRow[];\n}\n\n// ── DB Row Types ──\n\nexport interface EventRow {\n id: string;\n sessionId: string;\n taskId?: string;\n timestamp: string;\n eventType: string;\n process: string;\n pid: number;\n target?: string;\n targetType?: string;\n port?: number;\n durationMs?: number;\n}\n\nexport interface TaskRow {\n id: string;\n sessionId: string;\n description?: string;\n startedAt: string;\n completedAt?: string;\n steps: string;\n involvedServices: string;\n status: 'active' | 'completed' | 'cancelled';\n}\n\nexport interface WorkflowRow {\n id: string;\n sessionId: string;\n name?: string;\n pattern: string;\n taskIds: string;\n occurrences: number;\n firstSeen: string;\n lastSeen: string;\n avgDurationMs: number;\n involvedServices: string;\n}\n\nconst SCHEMA = `\nPRAGMA journal_mode = WAL;\nPRAGMA foreign_keys = ON;\nPRAGMA busy_timeout = 5000;\n\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n mode TEXT NOT NULL CHECK (mode IN ('discover')),\n started_at TEXT NOT NULL,\n completed_at TEXT,\n config TEXT NOT NULL DEFAULT '{}'\n);\n\nCREATE TABLE IF NOT EXISTS nodes (\n id TEXT NOT NULL,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n type TEXT NOT NULL,\n name TEXT NOT NULL,\n discovered_via TEXT,\n discovered_at TEXT NOT NULL,\n path_id TEXT,\n depth INTEGER DEFAULT 0,\n confidence REAL DEFAULT 0.5,\n metadata TEXT NOT NULL DEFAULT '{}',\n tags TEXT NOT NULL DEFAULT '[]',\n domain TEXT,\n sub_domain TEXT,\n quality_score REAL,\n PRIMARY KEY (id, session_id)\n);\n\nCREATE TABLE IF NOT EXISTS connections (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n source_asset_id TEXT NOT NULL,\n target_asset_id TEXT NOT NULL,\n type TEXT,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS edges (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n source_id TEXT NOT NULL,\n target_id TEXT NOT NULL,\n relationship TEXT NOT NULL,\n evidence TEXT,\n confidence REAL DEFAULT 0.5,\n discovered_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS activity_events (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n task_id TEXT,\n timestamp TEXT NOT NULL,\n event_type TEXT NOT NULL,\n process TEXT NOT NULL,\n pid INTEGER NOT NULL,\n target TEXT,\n target_type TEXT,\n port INTEGER,\n duration_ms INTEGER\n);\n\nCREATE TABLE IF NOT EXISTS tasks (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n description TEXT,\n started_at TEXT NOT NULL,\n completed_at TEXT,\n steps TEXT NOT NULL DEFAULT '[]',\n involved_services TEXT NOT NULL DEFAULT '[]',\n status TEXT DEFAULT 'active' CHECK (status IN ('active','completed','cancelled'))\n);\n\nCREATE TABLE IF NOT EXISTS workflows (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n name TEXT,\n pattern TEXT NOT NULL,\n task_ids TEXT NOT NULL DEFAULT '[]',\n occurrences INTEGER DEFAULT 1,\n first_seen TEXT NOT NULL,\n last_seen TEXT NOT NULL,\n avg_duration_ms INTEGER,\n involved_services TEXT NOT NULL DEFAULT '[]'\n);\n\nCREATE TABLE IF NOT EXISTS node_approvals (\n pattern TEXT PRIMARY KEY,\n action TEXT NOT NULL CHECK (action IN ('save','ignore','auto')),\n created_at TEXT NOT NULL\n);\n\nCREATE INDEX IF NOT EXISTS idx_nodes_session ON nodes(session_id);\nCREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(session_id, type);\nCREATE INDEX IF NOT EXISTS idx_edges_session ON edges(session_id);\nCREATE INDEX IF NOT EXISTS idx_edges_source ON edges(session_id, source_id);\nCREATE INDEX IF NOT EXISTS idx_edges_target ON edges(session_id, target_id);\nCREATE INDEX IF NOT EXISTS idx_events_session ON activity_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_events_task ON activity_events(task_id);\nCREATE INDEX IF NOT EXISTS idx_tasks_session ON tasks(session_id);\nCREATE INDEX IF NOT EXISTS idx_connections_session ON connections(session_id);\nCREATE INDEX IF NOT EXISTS idx_connections_lookup ON connections(session_id, source_asset_id, target_asset_id);\n`;\n\nexport class CartographyDB {\n private db: Database.Database;\n\n constructor(dbPath: string) {\n mkdirSync(dirname(dbPath), { recursive: true });\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.db.pragma('foreign_keys = ON');\n this.db.pragma('busy_timeout = 5000');\n this.migrate();\n }\n\n private migrate(): void {\n const version = (this.db.pragma('user_version', { simple: true }) as number);\n if (version === 0) {\n this.db.exec(SCHEMA);\n this.db.pragma('user_version = 4');\n return;\n } else if (version === 1) {\n // v1 → v2: add hex map columns to nodes + connections table\n const cols = (this.db.prepare(\"PRAGMA table_info(nodes)\").all() as Array<{ name: string }>).map(c => c.name);\n if (!cols.includes('domain')) this.db.exec('ALTER TABLE nodes ADD COLUMN domain TEXT');\n if (!cols.includes('sub_domain')) this.db.exec('ALTER TABLE nodes ADD COLUMN sub_domain TEXT');\n if (!cols.includes('quality_score')) this.db.exec('ALTER TABLE nodes ADD COLUMN quality_score REAL');\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS connections (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL REFERENCES sessions(id),\n source_asset_id TEXT NOT NULL,\n target_asset_id TEXT NOT NULL,\n type TEXT,\n created_at TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_connections_session ON connections(session_id);\n CREATE INDEX IF NOT EXISTS idx_connections_lookup ON connections(session_id, source_asset_id, target_asset_id);\n `);\n this.db.pragma('user_version = 3');\n }\n if (version === 2) {\n // v2 → v3: add composite index for connection upsert lookups\n this.db.exec('CREATE INDEX IF NOT EXISTS idx_connections_lookup ON connections(session_id, source_asset_id, target_asset_id)');\n this.db.pragma('user_version = 3');\n }\n // v3 → v4: add graph-traversal indexes (idempotent for any pre-v4 DB)\n const current = this.db.pragma('user_version', { simple: true }) as number;\n if (current < 4) {\n this.db.exec(`\n CREATE INDEX IF NOT EXISTS idx_nodes_type ON nodes(session_id, type);\n CREATE INDEX IF NOT EXISTS idx_edges_source ON edges(session_id, source_id);\n CREATE INDEX IF NOT EXISTS idx_edges_target ON edges(session_id, target_id);\n `);\n this.db.pragma('user_version = 4');\n }\n }\n\n close(): void {\n this.db.pragma('optimize');\n this.db.close();\n }\n\n /**\n * Advanced: the underlying better-sqlite3 connection. Used by the optional\n * semantic-search layer to load the `sqlite-vec` extension and manage its\n * virtual table. Prefer the typed methods above for everything else.\n */\n rawConnection(): Database.Database {\n return this.db;\n }\n\n // ── Sessions ────────────────────────────\n\n createSession(mode: 'discover', config: CartographyConfig): string {\n const id = crypto.randomUUID();\n this.db.prepare(\n 'INSERT INTO sessions (id, mode, started_at, config) VALUES (?, ?, ?, ?)'\n ).run(id, mode, new Date().toISOString(), JSON.stringify(config));\n return id;\n }\n\n endSession(id: string): void {\n this.db.prepare('UPDATE sessions SET completed_at = ? WHERE id = ?')\n .run(new Date().toISOString(), id);\n }\n\n getSession(id: string): SessionRow | undefined {\n const row = this.db.prepare('SELECT * FROM sessions WHERE id = ?').get(id) as Record<string, unknown> | undefined;\n return row ? this.mapSession(row) : undefined;\n }\n\n getLatestSession(mode?: string): SessionRow | undefined {\n const row = mode\n ? this.db.prepare('SELECT * FROM sessions WHERE mode = ? ORDER BY rowid DESC LIMIT 1').get(mode) as Record<string, unknown> | undefined\n : this.db.prepare('SELECT * FROM sessions ORDER BY rowid DESC LIMIT 1').get() as Record<string, unknown> | undefined;\n return row ? this.mapSession(row) : undefined;\n }\n\n getSessions(): SessionRow[] {\n const rows = this.db.prepare('SELECT * FROM sessions ORDER BY rowid DESC').all() as Record<string, unknown>[];\n return rows.map(r => this.mapSession(r));\n }\n\n private mapSession(r: Record<string, unknown>): SessionRow {\n const v = SessionRowSchema.parse(r);\n return {\n id: v.id,\n mode: v.mode,\n startedAt: v.started_at,\n completedAt: v.completed_at ?? undefined,\n config: v.config,\n };\n }\n\n // ── Nodes ───────────────────────────────\n\n upsertNode(sessionId: string, node: DiscoveryNode, depth = 0): void {\n this.db.prepare(`\n INSERT OR REPLACE INTO nodes\n (id, session_id, type, name, discovered_via, discovered_at, depth, confidence, metadata, tags,\n domain, sub_domain, quality_score)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n node.id, sessionId, node.type, node.name, node.discoveredVia,\n new Date().toISOString(), depth, node.confidence,\n JSON.stringify(node.metadata ?? {}),\n JSON.stringify(node.tags ?? []),\n node.domain ?? null,\n node.subDomain ?? null,\n node.qualityScore ?? null,\n );\n }\n\n getNodes(sessionId: string, opts?: { limit?: number; offset?: number }): NodeRow[] {\n let sql = 'SELECT * FROM nodes WHERE session_id = ?';\n if (opts?.limit) {\n sql += ` LIMIT ${opts.limit}`;\n if (opts.offset) sql += ` OFFSET ${opts.offset}`;\n }\n const rows = this.db.prepare(sql).all(sessionId) as Record<string, unknown>[];\n return rows.map(r => this.mapNode(r));\n }\n\n getNodeCount(sessionId: string): number {\n const row = this.db.prepare('SELECT COUNT(*) as cnt FROM nodes WHERE session_id = ?').get(sessionId) as { cnt: number };\n return row.cnt;\n }\n\n private mapNode(r: Record<string, unknown>): NodeRow {\n const v = NodeRowSchema.parse(r);\n return {\n id: v.id,\n sessionId: v.session_id,\n type: v.type,\n name: v.name,\n discoveredVia: v.discovered_via ?? '',\n discoveredAt: v.discovered_at,\n depth: v.depth,\n confidence: v.confidence,\n metadata: JSON.parse(v.metadata) as Record<string, unknown>,\n tags: JSON.parse(v.tags) as string[],\n pathId: v.path_id ?? undefined,\n domain: v.domain ?? undefined,\n subDomain: v.sub_domain ?? undefined,\n qualityScore: v.quality_score ?? undefined,\n };\n }\n\n deleteNode(sessionId: string, nodeId: string): void {\n this.db.prepare('DELETE FROM nodes WHERE session_id = ? AND id = ?').run(sessionId, nodeId);\n // Remove orphaned edges\n this.db.prepare(\n 'DELETE FROM edges WHERE session_id = ? AND (source_id = ? OR target_id = ?)'\n ).run(sessionId, nodeId, nodeId);\n }\n\n // ── Edges ───────────────────────────────\n\n insertEdge(sessionId: string, edge: DiscoveryEdge): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT OR IGNORE INTO edges\n (id, session_id, source_id, target_id, relationship, evidence, confidence, discovered_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, edge.sourceId, edge.targetId,\n edge.relationship, edge.evidence, edge.confidence,\n new Date().toISOString(),\n );\n }\n\n getEdges(sessionId: string, opts?: { limit?: number; offset?: number }): EdgeRow[] {\n let sql = 'SELECT * FROM edges WHERE session_id = ?';\n if (opts?.limit) {\n sql += ` LIMIT ${opts.limit}`;\n if (opts.offset) sql += ` OFFSET ${opts.offset}`;\n }\n const rows = this.db.prepare(sql).all(sessionId) as Record<string, unknown>[];\n return rows.map(r => {\n const v = EdgeRowSchema.parse(r);\n return {\n id: v.id,\n sessionId: v.session_id,\n sourceId: v.source_id,\n targetId: v.target_id,\n relationship: v.relationship,\n evidence: v.evidence ?? '',\n confidence: v.confidence,\n discoveredAt: v.discovered_at,\n };\n });\n }\n\n // ── Events ──────────────────────────────\n\n insertEvent(sessionId: string, event: Pick<EventRow, 'eventType' | 'process' | 'pid' | 'target' | 'targetType' | 'port'>, taskId?: string): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO activity_events\n (id, session_id, task_id, timestamp, event_type, process, pid, target, target_type, port)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, taskId ?? null, new Date().toISOString(),\n event.eventType, event.process, event.pid,\n event.target ?? null, event.targetType ?? null, event.port ?? null,\n );\n }\n\n getEvents(sessionId: string, since?: string): EventRow[] {\n const rows = since\n ? this.db.prepare('SELECT * FROM activity_events WHERE session_id = ? AND timestamp > ? ORDER BY timestamp').all(sessionId, since) as Record<string, unknown>[]\n : this.db.prepare('SELECT * FROM activity_events WHERE session_id = ? ORDER BY timestamp').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => {\n const v = EventRowSchema.parse(r);\n return {\n id: v.id,\n sessionId: v.session_id,\n taskId: v.task_id ?? undefined,\n timestamp: v.timestamp,\n eventType: v.event_type,\n process: v.process,\n pid: v.pid,\n target: v.target ?? undefined,\n targetType: v.target_type ?? undefined,\n port: v.port ?? undefined,\n durationMs: v.duration_ms ?? undefined,\n };\n });\n }\n\n // ── Tasks ───────────────────────────────\n\n startTask(sessionId: string, description?: string): string {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO tasks (id, session_id, description, started_at, steps, involved_services, status)\n VALUES (?, ?, ?, ?, '[]', '[]', 'active')\n `).run(id, sessionId, description ?? null, new Date().toISOString());\n return id;\n }\n\n endCurrentTask(sessionId: string): void {\n this.db.prepare(`\n UPDATE tasks SET status = 'completed', completed_at = ?\n WHERE session_id = ? AND status = 'active'\n `).run(new Date().toISOString(), sessionId);\n }\n\n updateTaskDescription(sessionId: string, description: string): void {\n this.db.prepare(`\n UPDATE tasks SET description = ?\n WHERE session_id = ? AND status = 'active'\n `).run(description, sessionId);\n }\n\n getActiveTask(sessionId: string): TaskRow | undefined {\n const row = this.db.prepare(\n \"SELECT * FROM tasks WHERE session_id = ? AND status = 'active' LIMIT 1\"\n ).get(sessionId) as Record<string, unknown> | undefined;\n return row ? this.mapTask(row) : undefined;\n }\n\n getTasks(sessionId: string): TaskRow[] {\n const rows = this.db.prepare('SELECT * FROM tasks WHERE session_id = ? ORDER BY started_at').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => this.mapTask(r));\n }\n\n private mapTask(r: Record<string, unknown>): TaskRow {\n const v = TaskRowSchema.parse(r);\n return {\n id: v.id,\n sessionId: v.session_id,\n description: v.description ?? undefined,\n startedAt: v.started_at,\n completedAt: v.completed_at ?? undefined,\n steps: v.steps,\n involvedServices: v.involved_services,\n status: v.status,\n };\n }\n\n // ── Workflows ───────────────────────────\n\n insertWorkflow(sessionId: string, data: Omit<WorkflowRow, 'id'>): void {\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO workflows\n (id, session_id, name, pattern, task_ids, occurrences,\n first_seen, last_seen, avg_duration_ms, involved_services)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `).run(\n id, sessionId, data.name ?? null, data.pattern,\n data.taskIds, data.occurrences,\n data.firstSeen, data.lastSeen, data.avgDurationMs,\n data.involvedServices,\n );\n }\n\n getWorkflows(sessionId: string): WorkflowRow[] {\n const rows = this.db.prepare('SELECT * FROM workflows WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => {\n const v = WorkflowRowSchema.parse(r);\n return {\n id: v.id,\n sessionId: v.session_id,\n name: v.name ?? undefined,\n pattern: v.pattern,\n taskIds: v.task_ids,\n occurrences: v.occurrences,\n firstSeen: v.first_seen,\n lastSeen: v.last_seen,\n avgDurationMs: v.avg_duration_ms ?? 0,\n involvedServices: v.involved_services,\n };\n });\n }\n\n // ── Connections (user-created hex map links) ─────────────────────────────\n\n upsertConnection(sessionId: string, conn: Omit<Connection, 'id'>): string {\n // Idempotent: same source+target+type = same connection\n const existing = this.db.prepare(\n 'SELECT id FROM connections WHERE session_id = ? AND source_asset_id = ? AND target_asset_id = ?'\n ).get(sessionId, conn.sourceAssetId, conn.targetAssetId) as { id: string } | undefined;\n if (existing) return existing.id;\n const id = crypto.randomUUID();\n this.db.prepare(`\n INSERT INTO connections (id, session_id, source_asset_id, target_asset_id, type, created_at)\n VALUES (?, ?, ?, ?, ?, ?)\n `).run(id, sessionId, conn.sourceAssetId, conn.targetAssetId, conn.type ?? null, new Date().toISOString());\n return id;\n }\n\n getConnections(sessionId: string): ConnectionRow[] {\n const rows = this.db.prepare('SELECT * FROM connections WHERE session_id = ?').all(sessionId) as Record<string, unknown>[];\n return rows.map(r => {\n const v = ConnectionRowSchema.parse(r);\n return {\n id: v.id,\n sessionId: v.session_id,\n sourceAssetId: v.source_asset_id,\n targetAssetId: v.target_asset_id,\n type: v.type ?? undefined,\n createdAt: v.created_at,\n };\n });\n }\n\n deleteConnection(sessionId: string, connectionId: string): void {\n this.db.prepare('DELETE FROM connections WHERE session_id = ? AND id = ?').run(sessionId, connectionId);\n }\n\n // ── Approvals ───────────────────────────\n\n setApproval(pattern: string, action: 'save' | 'ignore' | 'auto'): void {\n this.db.prepare(`\n INSERT OR REPLACE INTO node_approvals (pattern, action, created_at) VALUES (?, ?, ?)\n `).run(pattern, action, new Date().toISOString());\n }\n\n getApproval(pattern: string): string | undefined {\n const row = this.db.prepare('SELECT action FROM node_approvals WHERE pattern = ?').get(pattern) as { action: string } | undefined;\n return row?.action;\n }\n\n // ── Pruning ──────────────────────────────\n\n /**\n * Delete a session and all its associated data (nodes, edges, events, tasks, workflows, connections).\n */\n deleteSession(sessionId: string): void {\n this.db.prepare('DELETE FROM connections WHERE session_id = ?').run(sessionId);\n this.db.prepare('DELETE FROM workflows WHERE session_id = ?').run(sessionId);\n this.db.prepare('DELETE FROM activity_events WHERE session_id = ?').run(sessionId);\n this.db.prepare('DELETE FROM tasks WHERE session_id = ?').run(sessionId);\n this.db.prepare('DELETE FROM edges WHERE session_id = ?').run(sessionId);\n this.db.prepare('DELETE FROM nodes WHERE session_id = ?').run(sessionId);\n this.db.prepare('DELETE FROM sessions WHERE id = ?').run(sessionId);\n }\n\n /**\n * Prune sessions older than the given ISO date string. Returns count of deleted sessions.\n */\n pruneSessions(olderThan: string): number {\n const rows = this.db.prepare(\n 'SELECT id FROM sessions WHERE started_at < ?'\n ).all(olderThan) as { id: string }[];\n for (const row of rows) {\n this.deleteSession(row.id);\n }\n return rows.length;\n }\n\n // ── Graph queries (read-only context layer) ─────────────────────────────────\n\n /** Fetch a single node by id within a session. */\n getNode(sessionId: string, nodeId: string): NodeRow | undefined {\n const row = this.db.prepare('SELECT * FROM nodes WHERE session_id = ? AND id = ?')\n .get(sessionId, nodeId) as Record<string, unknown> | undefined;\n return row ? this.mapNode(row) : undefined;\n }\n\n /** Batch-fetch nodes by id, keyed for O(1) lookup. Chunked to stay under SQLite's bind-variable limit. */\n getNodesByIds(sessionId: string, ids: readonly string[]): Map<string, NodeRow> {\n const out = new Map<string, NodeRow>();\n for (let i = 0; i < ids.length; i += 900) {\n const chunk = ids.slice(i, i + 900);\n const placeholders = chunk.map(() => '?').join(',');\n const rows = this.db.prepare(\n `SELECT * FROM nodes WHERE session_id = ? AND id IN (${placeholders})`,\n ).all(sessionId, ...chunk) as Record<string, unknown>[];\n for (const r of rows) { const n = this.mapNode(r); out.set(n.id, n); }\n }\n return out;\n }\n\n /** Fetch all nodes of one or more types. */\n getNodesByType(sessionId: string, types: readonly string[]): NodeRow[] {\n if (types.length === 0) return [];\n const placeholders = types.map(() => '?').join(',');\n const rows = this.db.prepare(\n `SELECT * FROM nodes WHERE session_id = ? AND type IN (${placeholders})`,\n ).all(sessionId, ...types) as Record<string, unknown>[];\n return rows.map(r => this.mapNode(r));\n }\n\n /**\n * Lexical search over node id, name, domain, sub-domain and tags.\n * Case-insensitive substring match — the deterministic fallback for semantic search.\n */\n searchNodes(sessionId: string, query: string, opts?: { types?: readonly string[]; limit?: number }): NodeRow[] {\n const q = `%${query.trim().toLowerCase()}%`;\n const params: unknown[] = [sessionId, q, q, q, q, q];\n let sql = `\n SELECT * FROM nodes\n WHERE session_id = ?\n AND (\n lower(id) LIKE ? OR lower(name) LIKE ?\n OR lower(COALESCE(domain, '')) LIKE ?\n OR lower(COALESCE(sub_domain, '')) LIKE ?\n OR lower(tags) LIKE ?\n )`;\n if (opts?.types && opts.types.length > 0) {\n sql += ` AND type IN (${opts.types.map(() => '?').join(',')})`;\n params.push(...opts.types);\n }\n sql += ' ORDER BY confidence DESC';\n if (opts?.limit) sql += ` LIMIT ${Math.max(1, Math.floor(opts.limit))}`;\n const rows = this.db.prepare(sql).all(...params) as Record<string, unknown>[];\n return rows.map(r => this.mapNode(r));\n }\n\n /**\n * Traverse the dependency graph from a node using a recursive CTE with a\n * path-based cycle guard. `downstream` follows source→target (what the node\n * depends on / points to); `upstream` follows target→source (what depends on it).\n */\n getDependencies(\n sessionId: string,\n nodeId: string,\n opts: { direction?: 'downstream' | 'upstream' | 'both'; maxDepth?: number } = {},\n ): TraversalResult {\n const direction = opts.direction ?? 'downstream';\n const maxDepth = Math.max(1, Math.min(opts.maxDepth ?? 8, 64));\n const root = this.getNode(sessionId, nodeId);\n\n const depthById = new Map<string, number>();\n const collect = (dir: 'downstream' | 'upstream'): void => {\n // SEP = newline; node ids never contain newlines, so the path guard is collision-free.\n const [from, to] = dir === 'downstream' ? ['source_id', 'target_id'] : ['target_id', 'source_id'];\n const sql = `\n WITH RECURSIVE walk(node_id, depth, path) AS (\n SELECT ?, 0, char(10) || ? || char(10)\n UNION ALL\n SELECT e.${to}, w.depth + 1, w.path || e.${to} || char(10)\n FROM edges e JOIN walk w ON e.${from} = w.node_id\n WHERE e.session_id = ?\n AND w.depth < ?\n AND instr(w.path, char(10) || e.${to} || char(10)) = 0\n )\n SELECT node_id, MIN(depth) AS depth FROM walk WHERE node_id != ? GROUP BY node_id`;\n const rows = this.db.prepare(sql).all(nodeId, nodeId, sessionId, maxDepth, nodeId) as Array<{ node_id: string; depth: number }>;\n for (const r of rows) {\n const prev = depthById.get(r.node_id);\n if (prev === undefined || r.depth < prev) depthById.set(r.node_id, r.depth);\n }\n };\n\n if (direction === 'both') { collect('downstream'); collect('upstream'); }\n else collect(direction);\n\n const byId = this.getNodesByIds(sessionId, [...depthById.keys()]);\n const nodes = [...depthById.entries()]\n .map(([id, depth]) => { const n = byId.get(id); return n ? { ...n, depth } : undefined; })\n .filter((n): n is NodeRow & { depth: number } => n !== undefined)\n .sort((a, b) => a.depth - b.depth);\n\n // Edges that lie within the reached subgraph (including the root).\n const reachable = new Set<string>([nodeId, ...depthById.keys()]);\n const edges = this.getEdges(sessionId).filter(e => reachable.has(e.sourceId) && reachable.has(e.targetId));\n\n return { root, direction, maxDepth, nodes, edges };\n }\n\n /** Lightweight aggregate index of the whole topology — the progressive-disclosure summary. */\n getGraphSummary(sessionId: string): GraphSummary {\n const totals = {\n nodes: (this.db.prepare('SELECT COUNT(*) c FROM nodes WHERE session_id = ?').get(sessionId) as { c: number }).c,\n edges: (this.db.prepare('SELECT COUNT(*) c FROM edges WHERE session_id = ?').get(sessionId) as { c: number }).c,\n };\n const byType: Record<string, number> = {};\n for (const r of this.db.prepare('SELECT type, COUNT(*) c FROM nodes WHERE session_id = ? GROUP BY type').all(sessionId) as Array<{ type: string; c: number }>) {\n byType[r.type] = r.c;\n }\n const byDomain: Record<string, number> = {};\n for (const r of this.db.prepare(\"SELECT COALESCE(domain, '(none)') d, COUNT(*) c FROM nodes WHERE session_id = ? GROUP BY d\").all(sessionId) as Array<{ d: string; c: number }>) {\n byDomain[r.d] = r.c;\n }\n const byRelationship: Record<string, number> = {};\n for (const r of this.db.prepare('SELECT relationship rel, COUNT(*) c FROM edges WHERE session_id = ? GROUP BY rel').all(sessionId) as Array<{ rel: string; c: number }>) {\n byRelationship[r.rel] = r.c;\n }\n const topConnected = (this.db.prepare(`\n SELECT n.id, n.name, n.type, COUNT(e.id) AS degree\n FROM nodes n\n LEFT JOIN edges e ON e.session_id = n.session_id AND (e.source_id = n.id OR e.target_id = n.id)\n WHERE n.session_id = ?\n GROUP BY n.id, n.name, n.type\n ORDER BY degree DESC, n.confidence DESC\n LIMIT 10\n `).all(sessionId) as Array<{ id: string; name: string; type: string; degree: number }>);\n\n return { sessionId, totals, nodesByType: byType, nodesByDomain: byDomain, edgesByRelationship: byRelationship, topConnected };\n }\n\n // ── Stats ───────────────────────────────\n\n getStats(sessionId: string): { nodes: number; edges: number; events: number; tasks: number } {\n const nodes = (this.db.prepare('SELECT COUNT(*) as c FROM nodes WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const edges = (this.db.prepare('SELECT COUNT(*) as c FROM edges WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const events = (this.db.prepare('SELECT COUNT(*) as c FROM activity_events WHERE session_id = ?').get(sessionId) as { c: number }).c;\n const tasks = (this.db.prepare('SELECT COUNT(*) as c FROM tasks WHERE session_id = ?').get(sessionId) as { c: number }).c;\n return { nodes, edges, events, tasks };\n }\n}\n","/**\n * The Cartography MCP server — the package's primary, LLM-agnostic interface.\n *\n * It exposes the discovered infrastructure topology as Model Context Protocol\n * **Resources** (read-only context, progressive disclosure), a small set of query\n * **Tools** (parameterized lookups), and reusable **Prompts**. Any MCP host —\n * Claude Code, Cursor, Cline, Windsurf, the Vercel AI SDK, LangGraph — can drive\n * it; the package never needs to know which model is in use.\n */\n\nimport { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\nimport { CartographyDB } from '../db.js';\nimport type { GraphSummary } from '../db.js';\nimport { defaultConfig, NODE_TYPES, NODE_TYPE_GROUPS } from '../types.js';\nimport type { NodeRow } from '../types.js';\n\nconst SERVER_NAME = 'cartography';\nconst SERVER_VERSION = '2.0.0';\n\nconst SERVICE_TYPES = NODE_TYPE_GROUPS.web;\nconst DATA_TYPES = NODE_TYPE_GROUPS.data;\n\n/** A pluggable search backend; defaults to lexical search, can be upgraded to semantic. */\nexport type SearchFn = (\n db: CartographyDB,\n sessionId: string,\n query: string,\n opts: { types?: readonly string[]; limit: number },\n) => Promise<Array<{ node: NodeRow; score?: number }>>;\n\n/** A pluggable discovery backend invoked by the `run_discovery` tool. */\nexport type DiscoveryFn = (\n db: CartographyDB,\n sessionId: string,\n opts: { hint?: string },\n) => Promise<{ nodes: number; edges: number }>;\n\nexport interface CreateMcpServerOptions {\n /** Database instance. If omitted, one is opened at `config.dbPath`. */\n db?: CartographyDB;\n /** Path to the SQLite catalog (used when `db` is not provided). */\n dbPath?: string;\n /** Session to serve: a session id, or `'latest'` (default) for the newest discovery. */\n session?: string | 'latest';\n /** Semantic/lexical search backend. Defaults to lexical `searchNodes`. */\n search?: SearchFn;\n /** Discovery backend for `run_discovery`/`refresh`. Optional. */\n discovery?: DiscoveryFn;\n}\n\nconst lexicalSearch: SearchFn = async (db, sessionId, query, opts) =>\n db.searchNodes(sessionId, query, { types: opts.types, limit: opts.limit }).map((node) => ({ node }));\n\n/** Compact projection of a node for tool results (token-economical). */\nfunction compactNode(n: NodeRow): Record<string, unknown> {\n return {\n id: n.id,\n type: n.type,\n name: n.name,\n confidence: n.confidence,\n ...(n.domain ? { domain: n.domain } : {}),\n ...(n.tags.length ? { tags: n.tags } : {}),\n };\n}\n\nfunction json(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\nfunction summaryText(s: GraphSummary): string {\n const lines = [\n `# Infrastructure topology — session ${s.sessionId}`,\n ``,\n `Totals: ${s.totals.nodes} nodes, ${s.totals.edges} edges`,\n ``,\n `Nodes by type:`,\n ...Object.entries(s.nodesByType).sort((a, b) => b[1] - a[1]).map(([t, c]) => ` - ${t}: ${c}`),\n ``,\n `Nodes by domain:`,\n ...Object.entries(s.nodesByDomain).sort((a, b) => b[1] - a[1]).map(([d, c]) => ` - ${d}: ${c}`),\n ``,\n `Edges by relationship:`,\n ...Object.entries(s.edgesByRelationship).sort((a, b) => b[1] - a[1]).map(([r, c]) => ` - ${r}: ${c}`),\n ``,\n `Most connected:`,\n ...s.topConnected.map((n) => ` - ${n.id} (${n.type}) — degree ${n.degree}`),\n ``,\n `Read cartography://nodes/{id} or cartography://dependencies/{id} for detail.`,\n ];\n return lines.join('\\n');\n}\n\n/**\n * Build a fully-configured Cartography MCP server. Call `.connect(transport)` to run it.\n */\nexport function createMcpServer(opts: CreateMcpServerOptions = {}): McpServer {\n const db = opts.db ?? new CartographyDB(opts.dbPath ?? defaultConfig().dbPath);\n const search = opts.search ?? lexicalSearch;\n\n /** Resolve the served session id at call time (so late discoveries are picked up). */\n const resolveSession = (): string | undefined => {\n if (opts.session && opts.session !== 'latest') return opts.session;\n return db.getLatestSession('discover')?.id ?? db.getLatestSession()?.id;\n };\n\n const server = new McpServer(\n { name: SERVER_NAME, version: SERVER_VERSION },\n {\n capabilities: { resources: { subscribe: true, listChanged: true }, tools: {}, prompts: {}, logging: {} },\n instructions:\n 'Cartography exposes a discovered infrastructure/SaaS topology. Start by reading ' +\n 'cartography://graph/summary for a low-token overview, then drill into specific nodes ' +\n 'via cartography://nodes/{id} or query with the query_infrastructure / get_dependencies tools.',\n },\n );\n\n // ── Resources (read-only context, progressive disclosure) ──────────────────\n\n server.registerResource(\n 'graph-summary',\n 'cartography://graph/summary',\n { title: 'Topology summary', description: 'Low-token aggregate index of the whole landscape — read this first.', mimeType: 'text/markdown' },\n (uri) => {\n const sid = resolveSession();\n if (!sid) return { contents: [{ uri: uri.href, mimeType: 'text/markdown', text: 'No discovery session found. Run discovery first.' }] };\n return { contents: [{ uri: uri.href, mimeType: 'text/markdown', text: summaryText(db.getGraphSummary(sid)) }] };\n },\n );\n\n server.registerResource(\n 'nodes-index',\n 'cartography://nodes',\n { title: 'Node index', description: 'Lightweight list of all nodes (id, type, name only).', mimeType: 'application/json' },\n (uri) => {\n const sid = resolveSession();\n const nodes = sid ? db.getNodes(sid) : [];\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify({ count: nodes.length, nodes: nodes.map((n) => ({ id: n.id, type: n.type, name: n.name })) }, null, 2) }] };\n },\n );\n\n server.registerResource(\n 'node-detail',\n new ResourceTemplate('cartography://nodes/{id}', { list: undefined }),\n { title: 'Node detail', description: 'Full node record plus its incident edges.', mimeType: 'application/json' },\n (uri, variables) => {\n const sid = resolveSession();\n const id = decodeURIComponent(String(variables['id']));\n const node = sid ? db.getNode(sid, id) : undefined;\n if (!node) return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify({ error: `node not found: ${id}` }) }] };\n const edges = db.getEdges(sid!).filter((e) => e.sourceId === id || e.targetId === id);\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify({ node, edges }, null, 2) }] };\n },\n );\n\n const typedListResource = (name: string, uri: string, title: string, types: readonly string[]) =>\n server.registerResource(name, uri, { title, description: `Nodes of type: ${types.join(', ')}.`, mimeType: 'application/json' }, (u) => {\n const sid = resolveSession();\n const nodes = sid ? db.getNodesByType(sid, types) : [];\n return { contents: [{ uri: u.href, mimeType: 'application/json', text: JSON.stringify({ count: nodes.length, nodes: nodes.map(compactNode) }, null, 2) }] };\n });\n\n typedListResource('services', 'cartography://services', 'Services', SERVICE_TYPES);\n typedListResource('databases', 'cartography://databases', 'Data stores', DATA_TYPES);\n\n server.registerResource(\n 'dependencies',\n new ResourceTemplate('cartography://dependencies/{id}', { list: undefined }),\n { title: 'Dependencies', description: 'Transitive downstream dependencies of a node.', mimeType: 'application/json' },\n (uri, variables) => {\n const sid = resolveSession();\n const id = decodeURIComponent(String(variables['id']));\n if (!sid) return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify({ error: 'no session' }) }] };\n const r = db.getDependencies(sid, id, { direction: 'downstream', maxDepth: 8 });\n return { contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify({ root: id, count: r.nodes.length, nodes: r.nodes.map((n) => ({ ...compactNode(n), depth: n.depth })) }, null, 2) }] };\n },\n );\n\n server.registerResource(\n 'sessions',\n 'cartography://sessions',\n { title: 'Discovery sessions', description: 'All discovery sessions in the catalog.', mimeType: 'application/json' },\n (uri) => ({ contents: [{ uri: uri.href, mimeType: 'application/json', text: JSON.stringify(db.getSessions(), null, 2) }] }),\n );\n\n // ── Tools (model-controlled queries) ───────────────────────────────────────\n\n server.registerTool(\n 'get_summary',\n { title: 'Get topology summary', description: 'Low-token overview of the whole landscape (counts, types, domains, most-connected).', inputSchema: {} },\n () => {\n const sid = resolveSession();\n if (!sid) return json({ error: 'No discovery session found.' });\n return json(db.getGraphSummary(sid));\n },\n );\n\n server.registerTool(\n 'query_infrastructure',\n {\n title: 'Query infrastructure',\n description: 'Search the topology by name/id/domain (optionally filtered by node type). Returns compact node records.',\n inputSchema: {\n query: z.string().describe('Free-text query, e.g. \"postgres\", \"auth\", \"github\"'),\n types: z.array(z.enum(NODE_TYPES)).optional().describe('Restrict to these node types'),\n limit: z.number().int().min(1).max(200).default(25).optional(),\n },\n },\n async (args) => {\n const sid = resolveSession();\n if (!sid) return json({ error: 'No discovery session found.' });\n const results = await search(db, sid, args.query, { types: args.types, limit: args.limit ?? 25 });\n return json({ count: results.length, results: results.map((r) => ({ ...compactNode(r.node), ...(r.score !== undefined ? { score: r.score } : {}) })) });\n },\n );\n\n server.registerTool(\n 'search_topology',\n {\n title: 'Search topology (semantic)',\n description: 'Find nodes related to a concept by meaning (semantic search when available, lexical otherwise).',\n inputSchema: { query: z.string(), limit: z.number().int().min(1).max(100).default(10).optional() },\n },\n async (args) => {\n const sid = resolveSession();\n if (!sid) return json({ error: 'No discovery session found.' });\n const results = await search(db, sid, args.query, { limit: args.limit ?? 10 });\n return json({ count: results.length, results: results.map((r) => ({ ...compactNode(r.node), ...(r.score !== undefined ? { score: r.score } : {}) })) });\n },\n );\n\n server.registerTool(\n 'list_services',\n {\n title: 'List services',\n description: 'List discovered services or data stores.',\n inputSchema: { kind: z.enum(['services', 'databases', 'all']).default('all').optional() },\n },\n (args) => {\n const sid = resolveSession();\n if (!sid) return json({ error: 'No discovery session found.' });\n const kind = args.kind ?? 'all';\n const types = kind === 'services' ? SERVICE_TYPES : kind === 'databases' ? DATA_TYPES : [...SERVICE_TYPES, ...DATA_TYPES];\n return json(db.getNodesByType(sid, types).map(compactNode));\n },\n );\n\n server.registerTool(\n 'get_node',\n { title: 'Get node', description: 'Fetch a single node with its incident edges.', inputSchema: { id: z.string() } },\n (args) => {\n const sid = resolveSession();\n if (!sid) return json({ error: 'No discovery session found.' });\n const node = db.getNode(sid, args.id);\n if (!node) return json({ error: `node not found: ${args.id}` });\n const edges = db.getEdges(sid).filter((e) => e.sourceId === args.id || e.targetId === args.id);\n return json({ node, edges });\n },\n );\n\n server.registerTool(\n 'get_dependencies',\n {\n title: 'Get dependencies',\n description: 'Traverse the dependency graph from a node (downstream/upstream/both) with a depth limit.',\n inputSchema: {\n id: z.string(),\n direction: z.enum(['downstream', 'upstream', 'both']).default('downstream').optional(),\n maxDepth: z.number().int().min(1).max(64).default(8).optional(),\n },\n },\n (args) => {\n const sid = resolveSession();\n if (!sid) return json({ error: 'No discovery session found.' });\n const r = db.getDependencies(sid, args.id, { direction: args.direction ?? 'downstream', maxDepth: args.maxDepth ?? 8 });\n return json({\n root: r.root ? compactNode(r.root) : null,\n direction: r.direction,\n count: r.nodes.length,\n nodes: r.nodes.map((n) => ({ ...compactNode(n), depth: n.depth })),\n edges: r.edges.map((e) => ({ from: e.sourceId, to: e.targetId, rel: e.relationship })),\n });\n },\n );\n\n if (opts.discovery) {\n const discovery = opts.discovery;\n server.registerTool(\n 'run_discovery',\n {\n title: 'Run discovery',\n description: 'Scan the local system (read-only) and update the catalog. Returns counts of nodes/edges found.',\n inputSchema: { hint: z.string().optional().describe('Optional focus, e.g. tool names to look for') },\n },\n async (args) => {\n let sid = resolveSession();\n if (!sid) sid = db.createSession('discover', defaultConfig());\n const result = await discovery(db, sid, { hint: args.hint });\n server.server.sendResourceUpdated({ uri: 'cartography://graph/summary' }).catch(() => {});\n server.server.sendResourceListChanged?.();\n return json({ session: sid, ...result });\n },\n );\n }\n\n // ── Prompts (user-controlled templates) ────────────────────────────────────\n\n server.registerPrompt(\n 'audit-attack-surface',\n { title: 'Audit attack surface', description: 'Review the discovered topology for externally-reachable services and risky dependencies.' },\n () => ({\n messages: [{\n role: 'user', content: { type: 'text', text:\n 'Read cartography://graph/summary and cartography://services. Identify externally-reachable ' +\n 'services, data stores with broad inbound dependencies, and any node with low confidence that ' +\n 'warrants verification. Use get_dependencies to assess blast radius. Summarize the attack surface ' +\n 'and concrete hardening recommendations.' } }],\n }),\n );\n\n server.registerPrompt(\n 'map-service-dependencies',\n {\n title: 'Map service dependencies',\n description: 'Produce a dependency map for a given service.',\n argsSchema: { service: z.string().describe('Service node id or name') },\n },\n (args) => ({\n messages: [{\n role: 'user', content: { type: 'text', text:\n `Use query_infrastructure to locate \"${args.service}\", then get_dependencies (direction=both) to ` +\n `map everything it depends on and everything that depends on it. Present the result as a clear ` +\n `dependency tree and call out single points of failure.` } }],\n }),\n );\n\n server.registerPrompt(\n 'onboard-to-system',\n { title: 'Onboard to system', description: 'Explain the system landscape to a new engineer.' },\n () => ({\n messages: [{\n role: 'user', content: { type: 'text', text:\n 'Read cartography://graph/summary, then cartography://services and cartography://databases. ' +\n 'Write a concise onboarding briefing for a new engineer: what the major systems are, how they ' +\n 'connect, which data stores are central, and where to look first.' } }],\n }),\n );\n\n return server;\n}\n","/**\n * Transport bindings for the Cartography MCP server.\n *\n * - **stdio**: the local-first default — zero network, every client supports it.\n * - **Streamable HTTP**: a single `/mcp` endpoint for team/remote use, bound to\n * localhost with DNS-rebinding protection. The deprecated SSE transport is not used.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport http from 'node:http';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n\n/** Connect a server over stdio (resolves when the transport closes). */\nexport async function runStdio(server: McpServer): Promise<void> {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nexport interface HttpOptions {\n port?: number;\n host?: string;\n /** Extra allowed Host headers (defaults to localhost:port variants). */\n allowedHosts?: string[];\n /** Allowed Origin headers (defaults to none → same-origin only). */\n allowedOrigins?: string[];\n}\n\nasync function readJsonBody(req: http.IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n if (chunks.length === 0) return undefined;\n try { return JSON.parse(Buffer.concat(chunks).toString('utf8')); } catch { return undefined; }\n}\n\n/**\n * Start a Streamable HTTP server. A fresh MCP server instance is created per\n * session via `factory`, so multiple clients can connect concurrently.\n */\nexport async function runHttp(factory: () => McpServer, opts: HttpOptions = {}): Promise<http.Server> {\n const host = opts.host ?? '127.0.0.1';\n const port = opts.port ?? 3737;\n const allowedHosts = opts.allowedHosts ?? [`${host}:${port}`, `localhost:${port}`, `127.0.0.1:${port}`];\n const transports = new Map<string, StreamableHTTPServerTransport>();\n\n const httpServer = http.createServer(async (req, res) => {\n try {\n const url = req.url ?? '';\n if (!url.startsWith('/mcp')) { res.writeHead(404, { 'content-type': 'application/json' }).end('{\"error\":\"not found\"}'); return; }\n\n const sessionId = req.headers['mcp-session-id'] as string | undefined;\n const existing = sessionId ? transports.get(sessionId) : undefined;\n\n if (existing) {\n const body = req.method === 'POST' ? await readJsonBody(req) : undefined;\n await existing.handleRequest(req, res, body);\n return;\n }\n\n if (req.method !== 'POST') {\n res.writeHead(400, { 'content-type': 'application/json' }).end('{\"error\":\"missing or unknown mcp-session-id\"}');\n return;\n }\n\n // New session: initialize a transport + server instance.\n const body = await readJsonBody(req);\n const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n enableDnsRebindingProtection: true,\n allowedHosts,\n ...(opts.allowedOrigins ? { allowedOrigins: opts.allowedOrigins } : {}),\n onsessioninitialized: (id: string) => { transports.set(id, transport); },\n });\n transport.onclose = () => { if (transport.sessionId) transports.delete(transport.sessionId); };\n await factory().connect(transport);\n await transport.handleRequest(req, res, body);\n } catch {\n if (!res.headersSent) res.writeHead(500, { 'content-type': 'application/json' }).end('{\"error\":\"internal error\"}');\n }\n });\n\n await new Promise<void>((resolve) => httpServer.listen(port, host, resolve));\n return httpServer;\n}\n","/** FNV-1a (32-bit) — the shared content hash used by the embeddings and vector store. */\nexport function fnv1a(s: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n","/**\n * Embedding providers for semantic search.\n *\n * The default provider runs a small sentence-transformer locally via\n * `@huggingface/transformers` (no API key, offline after first download), keeping\n * the package LLM-agnostic. Everything is a lazy import so installs that never use\n * semantic search pay no cost and need no native model.\n */\n\nimport { fnv1a } from './hash.js';\n\n/** Produces fixed-dimension embeddings for a batch of texts. */\nexport interface EmbeddingProvider {\n readonly id: string;\n readonly dimensions: number;\n embed(texts: string[]): Promise<Float32Array[]>;\n}\n\n/**\n * Local sentence-transformer embedder (Xenova/all-MiniLM-L6-v2, 384 dims).\n * Returns `undefined` if `@huggingface/transformers` is not installed or the\n * model cannot be loaded, so callers can fall back to lexical search.\n */\nexport async function createLocalEmbedder(\n model = 'Xenova/all-MiniLM-L6-v2',\n): Promise<EmbeddingProvider | undefined> {\n try {\n // Cast the specifier to defeat static module resolution: the type build must\n // not require this optional native dep to be installed. We assert the minimal\n // surface we use instead — the runtime import is unchanged.\n const tf = (await import('@huggingface/transformers' as string)) as {\n pipeline(\n task: string,\n model: string,\n ): Promise<(text: string, opts: { pooling: string; normalize: boolean }) => Promise<{ data: unknown }>>;\n };\n const extractor = await tf.pipeline('feature-extraction', model);\n return {\n id: `local:${model}`,\n dimensions: 384,\n async embed(texts: string[]): Promise<Float32Array[]> {\n const out: Float32Array[] = [];\n for (const text of texts) {\n const tensor = await extractor(text, { pooling: 'mean', normalize: true });\n out.push(Float32Array.from(tensor.data as Iterable<number>));\n }\n return out;\n },\n };\n } catch {\n return undefined;\n }\n}\n\n/**\n * A deterministic, dependency-free hashing embedder (bag-of-character-ngrams).\n * Not as good as a transformer, but offline, instant, and useful as a fallback\n * and for tests. Produces L2-normalized vectors.\n */\nexport function createHashEmbedder(dimensions = 256): EmbeddingProvider {\n return {\n id: `hash:${dimensions}`,\n dimensions,\n async embed(texts: string[]): Promise<Float32Array[]> {\n return texts.map((text) => hashEmbed(text, dimensions));\n },\n };\n}\n\nfunction hashEmbed(text: string, dim: number): Float32Array {\n const v = new Float32Array(dim);\n const tokens = text.toLowerCase().match(/[a-z0-9]+/g) ?? [];\n for (const tok of tokens) {\n // hash the token and its char trigrams into buckets\n for (const gram of [tok, ...trigrams(tok)]) {\n const h = fnv1a(gram);\n v[h % dim] += 1;\n }\n }\n let norm = 0;\n for (const x of v) norm += x * x;\n norm = Math.sqrt(norm) || 1;\n for (let i = 0; i < dim; i++) v[i] = v[i]! / norm;\n return v;\n}\n\nfunction trigrams(s: string): string[] {\n if (s.length < 3) return [];\n const out: string[] = [];\n for (let i = 0; i <= s.length - 3; i++) out.push(s.slice(i, i + 3));\n return out;\n}\n","/**\n * Vector store backed by `sqlite-vec`. Stores one embedding per node in a `vec0`\n * virtual table living inside the same SQLite catalog, with incremental indexing\n * (content-hashed) so re-runs only embed what changed.\n */\n\nimport type { CartographyDB } from '../db.js';\nimport type { NodeRow } from '../types.js';\nimport type { EmbeddingProvider } from './embeddings.js';\nimport { fnv1a } from './hash.js';\n\n/** Text used to represent a node for embedding. */\nexport function nodeText(n: NodeRow): string {\n const desc = typeof n.metadata?.['description'] === 'string' ? (n.metadata['description'] as string) : '';\n const category = typeof n.metadata?.['category'] === 'string' ? (n.metadata['category'] as string) : '';\n return [n.name, n.id.replace(/[:_]/g, ' '), `type ${n.type}`, n.domain ?? '', n.subDomain ?? '', category, n.tags.join(' '), desc]\n .filter(Boolean).join(' — ');\n}\n\nfunction hash(s: string): string {\n return fnv1a(s).toString(16);\n}\n\nfunction toBuffer(v: Float32Array): Buffer {\n return Buffer.from(v.buffer, v.byteOffset, v.byteLength);\n}\n\nexport class VectorStore {\n private loaded = false;\n\n constructor(private db: CartographyDB, private embedder: EmbeddingProvider) {}\n\n /** Load sqlite-vec and ensure the schema exists. Returns false if unavailable. */\n async init(): Promise<boolean> {\n if (this.loaded) return true;\n try {\n const conn = this.db.rawConnection();\n // Cast the specifier so the type build doesn't require this optional native\n // dep to be installed; runtime import is unchanged.\n const sqliteVec = (await import('sqlite-vec' as string)) as { load(db: unknown): void };\n sqliteVec.load(conn);\n conn.exec(`\n CREATE TABLE IF NOT EXISTS vec_index (\n rowid INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n node_id TEXT NOT NULL,\n hash TEXT NOT NULL,\n UNIQUE(session_id, node_id)\n );\n CREATE TABLE IF NOT EXISTS vec_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);\n `);\n // Recreate the vector table if the embedding dimensions changed.\n const dimRow = conn.prepare(\"SELECT value FROM vec_meta WHERE key = 'dims'\").get() as { value: string } | undefined;\n const dims = this.embedder.dimensions;\n if (dimRow && Number(dimRow.value) !== dims) {\n conn.exec('DROP TABLE IF EXISTS vec_nodes; DELETE FROM vec_index;');\n }\n conn.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS vec_nodes USING vec0(embedding float[${dims}])`);\n conn.prepare('INSERT OR REPLACE INTO vec_meta(key, value) VALUES (?, ?)').run('dims', String(dims));\n conn.prepare('INSERT OR REPLACE INTO vec_meta(key, value) VALUES (?, ?)').run('embedder', this.embedder.id);\n this.loaded = true;\n return true;\n } catch {\n return false;\n }\n }\n\n /** Incrementally embed and index any new/changed nodes for a session. */\n async index(sessionId: string): Promise<{ embedded: number; total: number }> {\n if (!(await this.init())) return { embedded: 0, total: 0 };\n const conn = this.db.rawConnection();\n const nodes = this.db.getNodes(sessionId);\n\n const getRow = conn.prepare('SELECT rowid, hash FROM vec_index WHERE session_id = ? AND node_id = ?');\n const insIndex = conn.prepare('INSERT INTO vec_index (session_id, node_id, hash) VALUES (?, ?, ?)');\n const updHash = conn.prepare('UPDATE vec_index SET hash = ? WHERE rowid = ?');\n const delVec = conn.prepare('DELETE FROM vec_nodes WHERE rowid = ?');\n const insVec = conn.prepare('INSERT INTO vec_nodes (rowid, embedding) VALUES (?, ?)');\n\n const pending: Array<{ rowid: bigint; text: string }> = [];\n for (const n of nodes) {\n const text = nodeText(n);\n const h = hash(`${this.embedder.id}:${text}`);\n const existing = getRow.get(sessionId, n.id) as { rowid: number; hash: string } | undefined;\n if (existing) {\n if (existing.hash === h) continue;\n updHash.run(h, existing.rowid);\n delVec.run(BigInt(existing.rowid));\n pending.push({ rowid: BigInt(existing.rowid), text });\n } else {\n const info = insIndex.run(sessionId, n.id, h);\n pending.push({ rowid: BigInt(info.lastInsertRowid as number), text });\n }\n }\n\n if (pending.length > 0) {\n const vectors = await this.embedder.embed(pending.map((p) => p.text));\n const tx = conn.transaction(() => {\n pending.forEach((p, i) => insVec.run(p.rowid, toBuffer(vectors[i]!)));\n });\n tx();\n }\n return { embedded: pending.length, total: nodes.length };\n }\n\n /** k-nearest-neighbour search within a session. Returns node ids + distances. */\n async search(sessionId: string, query: string, k: number): Promise<Array<{ nodeId: string; distance: number }>> {\n if (!(await this.init())) return [];\n await this.index(sessionId);\n const conn = this.db.rawConnection();\n const [qv] = await this.embedder.embed([query]);\n if (!qv) return [];\n\n // Pure-vec KNN scan (most compatible form), then map rowids and filter by\n // session in JS. Over-fetch so cross-session neighbours don't crowd out hits.\n const overfetch = Math.max(k * 5, k);\n const knn = conn.prepare(\n 'SELECT rowid, distance FROM vec_nodes WHERE embedding MATCH ? ORDER BY distance LIMIT ?',\n ).all(toBuffer(qv), overfetch) as Array<{ rowid: number; distance: number }>;\n\n const meta = conn.prepare('SELECT node_id AS nodeId, session_id AS sessionId FROM vec_index WHERE rowid = ?');\n const out: Array<{ nodeId: string; distance: number }> = [];\n for (const row of knn) {\n const m = meta.get(row.rowid) as { nodeId: string; sessionId: string } | undefined;\n if (m && m.sessionId === sessionId) out.push({ nodeId: m.nodeId, distance: row.distance });\n if (out.length >= k) break;\n }\n return out;\n }\n}\n","/**\n * Semantic search backend for the MCP server. Wraps a {@link VectorStore} and\n * degrades gracefully to lexical search when embeddings/sqlite-vec are unavailable\n * or return nothing.\n */\n\nimport type { CartographyDB } from '../db.js';\nimport type { NodeRow } from '../types.js';\nimport type { SearchFn } from '../mcp/server.js';\nimport type { EmbeddingProvider } from './embeddings.js';\nimport { createLocalEmbedder } from './embeddings.js';\nimport { VectorStore } from './store.js';\n\nconst lexical = (db: CartographyDB, sessionId: string, query: string, opts: { types?: readonly string[]; limit: number }) =>\n db.searchNodes(sessionId, query, { types: opts.types, limit: opts.limit }).map((node) => ({ node }));\n\n/** A lexical-only {@link SearchFn} — the fallback when no embedder/vector store is available. */\nconst lexicalSearch = (): SearchFn => async (d, sid, q, opts) => lexical(d, sid, q, opts);\n\n/**\n * Build a {@link SearchFn} that prefers semantic (vector) search and falls back to\n * lexical. Pass an explicit embedder, or let it lazily load the local transformer\n * (returns a lexical-only function if none is available).\n */\nexport async function createSemanticSearch(\n db: CartographyDB,\n embedder?: EmbeddingProvider,\n): Promise<SearchFn> {\n const provider = embedder ?? (await createLocalEmbedder());\n if (!provider) return lexicalSearch();\n const store = new VectorStore(db, provider);\n const ok = await store.init();\n if (!ok) return lexicalSearch();\n\n return async (d, sid, query, opts): Promise<Array<{ node: NodeRow; score?: number }>> => {\n const hits = await store.search(sid, query, opts.limit);\n if (hits.length === 0) return lexical(d, sid, query, opts);\n // Materialize only the hit nodes, not the whole session.\n const byId = d.getNodesByIds(sid, hits.map((h) => h.nodeId));\n const results: Array<{ node: NodeRow; score?: number }> = [];\n for (const h of hits) {\n const node = byId.get(h.nodeId);\n if (!node) continue; // vector outlived its node (deleted since last index)\n if (opts.types && opts.types.length > 0 && !opts.types.includes(node.type)) continue;\n // cosine distance → similarity score in [0,1]\n results.push({ node, score: Math.max(0, 1 - h.distance / 2) });\n }\n return results.length > 0 ? results : lexical(d, sid, query, opts);\n };\n}\n\nexport { VectorStore } from './store.js';\nexport { createLocalEmbedder, createHashEmbedder } from './embeddings.js';\nexport type { EmbeddingProvider } from './embeddings.js';\n","/**\n * Scanner plugin contract.\n *\n * A scanner detects whether it applies to the current machine, then produces a\n * read-only {@link ScanResult}: deterministic nodes/edges where the data is\n * structured enough, plus an optional raw report for an LLM to classify further.\n *\n * Modeled on Steampipe plugins / Backstage processors: new sources can be added\n * (in-tree or via `@datasynx/scanner-*` packages) and registered without forking\n * the core. Each scanner declares the commands it needs, feeding the safety layer.\n */\n\nimport type { Platform } from '../platform.js';\nimport type { DiscoveryNode, DiscoveryEdge } from '../types.js';\n\nexport interface ScanContext {\n /** Optional focus hint from the caller (e.g. tool names to look for). */\n hint?: string;\n /** The current platform. */\n platform: Platform;\n /** Allowlist-gated command runner (returns '' on error/blocked). */\n run: (cmd: string, opts?: { timeout?: number; env?: NodeJS.ProcessEnv }) => string;\n}\n\nexport interface ScanResult {\n /** Deterministically classified nodes. */\n nodes: DiscoveryNode[];\n /** Deterministically classified edges. */\n edges: DiscoveryEdge[];\n /** Optional raw text report for LLM-driven classification. */\n report?: string;\n}\n\nexport interface Scanner {\n /** Stable id, e.g. \"bookmarks\", \"installed-apps\", \"cloud-aws\". */\n id: string;\n /** Human-readable title. */\n title: string;\n /** Platforms this scanner supports, or 'all'. */\n platforms: Platform[] | 'all';\n /** Read-only commands this scanner may run (declared for the safety layer/docs). */\n allowedCommands?: string[];\n /** Cheap check whether the scanner applies here (e.g. a CLI is installed). */\n detect(ctx: ScanContext): boolean | Promise<boolean>;\n /** Perform the read-only scan. */\n scan(ctx: ScanContext): Promise<ScanResult>;\n}\n\n/** A typed registry of scanners with lazy, platform-aware selection. */\nexport class ScannerRegistry {\n private scanners = new Map<string, Scanner>();\n\n register(scanner: Scanner): this {\n if (this.scanners.has(scanner.id)) throw new Error(`scanner already registered: ${scanner.id}`);\n this.scanners.set(scanner.id, scanner);\n return this;\n }\n\n get(id: string): Scanner | undefined {\n return this.scanners.get(id);\n }\n\n list(): Scanner[] {\n return [...this.scanners.values()];\n }\n\n /** Scanners whose `platforms` include the given platform. */\n forPlatform(platform: Platform): Scanner[] {\n return this.list().filter((s) => s.platforms === 'all' || s.platforms.includes(platform));\n }\n}\n","import type { Scanner, ScanResult } from './types.js';\nimport type { DiscoveryNode } from '../types.js';\nimport { scanAllBookmarks } from '../bookmarks.js';\n\n/** Hostname substrings that indicate a personal site — never catalogued. */\nconst PERSONAL = [\n 'facebook.', 'instagram.', 'twitter.', 'x.com', 'tiktok.', 'reddit.', 'youtube.', 'netflix.',\n 'spotify.', 'twitch.', 'pinterest.', 'snapchat.', 'whatsapp.', 'amazon.', 'ebay.', 'aliexpress.',\n 'cnn.', 'bbc.', 'nytimes.', 'espn.', 'booking.', 'airbnb.', 'tripadvisor.', 'wikipedia.',\n];\n\n/** Well-known business/SaaS hostnames → catalogued as saas_tool. */\nconst BUSINESS = [\n 'github.', 'gitlab.', 'bitbucket.', 'atlassian.', 'jira.', 'confluence.', 'notion.', 'linear.',\n 'slack.', 'zoom.', 'figma.', 'miro.', 'vercel.', 'netlify.', 'heroku.', 'datadog', 'sentry.',\n 'grafana.', 'pagerduty.', 'aws.amazon.', 'console.cloud.google', 'portal.azure', 'cloudflare.',\n 'hubspot.', 'salesforce.', 'stripe.', 'twilio.', 'sendgrid.', 'mailchimp.', 'segment.', 'mixpanel.',\n 'amplitude.', 'looker.', 'tableau.', 'snowflake.', 'databricks.', 'mongodb.', 'redis.', 'elastic.',\n 'openai.', 'anthropic.', 'huggingface.', 'docker.', 'npmjs.', 'pypi.', 'circleci.', 'travis-ci.',\n 'jenkins.', 'terraform.', 'hashicorp.', 'okta.', 'auth0.', '1password.', 'asana.', 'trello.', 'monday.',\n];\n\nfunction classify(hostname: string): { type: DiscoveryNode['type']; confidence: number } | null {\n const h = hostname.toLowerCase();\n if (PERSONAL.some((p) => h.includes(p))) return null;\n if (BUSINESS.some((b) => h.includes(b))) return { type: 'saas_tool', confidence: 0.7 };\n // Internal/custom hosts (IPs or *.company.tld with non-standard ports) → web_service\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(h) || /\\.(internal|local|corp|lan)\\b/.test(h)) {\n return { type: 'web_service', confidence: 0.6 };\n }\n return null; // unknown public host — leave for LLM-driven classification\n}\n\nexport const bookmarksScanner: Scanner = {\n id: 'bookmarks',\n title: 'Browser bookmarks',\n platforms: 'all',\n detect: () => true,\n async scan(): Promise<ScanResult> {\n const hosts = await scanAllBookmarks();\n const seen = new Set<string>();\n const nodes: DiscoveryNode[] = [];\n for (const host of hosts) {\n const klass = classify(host.hostname);\n if (!klass) continue;\n const id = `${klass.type}:${host.hostname}`;\n if (seen.has(id)) continue;\n seen.add(id);\n nodes.push({\n id, type: klass.type, name: host.hostname, discoveredVia: 'bookmark',\n confidence: klass.confidence, tags: ['bookmark'],\n metadata: { protocol: host.protocol, ...(host.port ? { port: host.port } : {}) },\n });\n }\n return { nodes, edges: [] };\n },\n};\n","import type { Scanner, ScanResult } from './types.js';\nimport type { DiscoveryNode } from '../types.js';\nimport { commandExists } from '../platform.js';\n\n/** Known CLIs/tools grouped by category — detected deterministically via `commandExists`. */\nconst KNOWN_TOOLS: Record<string, string[]> = {\n ide: ['code', 'code-insiders', 'cursor', 'windsurf', 'zed', 'nvim', 'vim', 'emacs', 'idea', 'webstorm', 'pycharm', 'goland', 'datagrip', 'clion', 'rider', 'phpstorm'],\n 'dev-tool': ['git', 'gh', 'docker', 'docker-compose', 'podman', 'kubectl', 'helm', 'terraform', 'ansible', 'vagrant', 'packer', 'consul', 'vault', 'nomad'],\n runtime: ['node', 'npm', 'pnpm', 'yarn', 'bun', 'deno', 'python', 'python3', 'pip', 'poetry', 'ruby', 'rails', 'java', 'mvn', 'gradle', 'go', 'cargo', 'rustc', 'php', 'composer', 'dotnet'],\n database: ['psql', 'mysql', 'mongosh', 'redis-cli', 'sqlite3', 'clickhouse-client'],\n cloud: ['aws', 'gcloud', 'az', 'heroku', 'fly', 'vercel', 'netlify', 'wrangler', 'supabase'],\n browser: ['google-chrome', 'chromium', 'firefox', 'brave', 'opera'],\n observability: ['prometheus', 'grafana-cli', 'datadog-agent', 'newrelic-agent'],\n};\n\nexport const installedAppsScanner: Scanner = {\n id: 'installed-apps',\n title: 'Installed apps & developer tools',\n platforms: 'all',\n allowedCommands: ['which', 'command', 'Get-Command'],\n detect: () => true,\n async scan(ctx): Promise<ScanResult> {\n const nodes: DiscoveryNode[] = [];\n const hintTerms = (ctx.hint ?? '').toLowerCase().split(/[\\s,]+/).filter(Boolean);\n for (const [category, tools] of Object.entries(KNOWN_TOOLS)) {\n for (const tool of tools) {\n const path = commandExists(tool);\n if (!path) continue;\n const boosted = hintTerms.some((t) => tool.includes(t));\n nodes.push({\n id: `saas_tool:${tool}`,\n type: 'saas_tool',\n name: tool,\n discoveredVia: 'installed-app',\n confidence: boosted ? 0.95 : 0.9,\n tags: [category],\n metadata: { category, path },\n });\n }\n }\n return { nodes, edges: [] };\n },\n};\n","import type { Scanner, ScanResult } from './types.js';\nimport type { DiscoveryNode, NodeType } from '../types.js';\nimport { scanListeningPorts } from '../platform.js';\n\n/** Well-known listening ports → node type + service name. */\nconst PORT_MAP: Record<number, { type: NodeType; service: string }> = {\n 5432: { type: 'database_server', service: 'postgresql' },\n 3306: { type: 'database_server', service: 'mysql' },\n 1433: { type: 'database_server', service: 'sqlserver' },\n 27017: { type: 'database_server', service: 'mongodb' },\n 9200: { type: 'database_server', service: 'elasticsearch' },\n 6379: { type: 'cache_server', service: 'redis' },\n 11211: { type: 'cache_server', service: 'memcached' },\n 9092: { type: 'message_broker', service: 'kafka' },\n 5672: { type: 'message_broker', service: 'rabbitmq' },\n 4222: { type: 'message_broker', service: 'nats' },\n 9090: { type: 'web_service', service: 'prometheus' },\n 3000: { type: 'web_service', service: 'http-app' },\n 8080: { type: 'web_service', service: 'http-app' },\n 8000: { type: 'web_service', service: 'http-app' },\n 80: { type: 'web_service', service: 'http' },\n 443: { type: 'web_service', service: 'https' },\n 8200: { type: 'web_service', service: 'vault' },\n 8500: { type: 'web_service', service: 'consul' },\n 2379: { type: 'web_service', service: 'etcd' },\n 5601: { type: 'web_service', service: 'kibana' },\n 15672: { type: 'web_service', service: 'rabbitmq-management' },\n};\n\n/** Extract distinct listening port numbers from ss/lsof/PowerShell output. */\nexport function extractListeningPorts(raw: string): number[] {\n const ports = new Set<number>();\n for (const m of raw.matchAll(/[:.](\\d{2,5})\\b/g)) {\n const p = Number(m[1]);\n if (p in PORT_MAP) ports.add(p);\n }\n return [...ports];\n}\n\nexport const portsScanner: Scanner = {\n id: 'local-ports',\n title: 'Local listening ports',\n platforms: 'all',\n allowedCommands: ['ss', 'lsof', 'Get-NetTCPConnection'],\n detect: () => true,\n async scan(): Promise<ScanResult> {\n const raw = scanListeningPorts();\n const nodes: DiscoveryNode[] = [];\n for (const port of extractListeningPorts(raw)) {\n const { type, service } = PORT_MAP[port]!;\n nodes.push({\n id: `${type}:localhost:${port}`,\n type,\n name: `${service} (:${port})`,\n discoveredVia: 'listening-port',\n confidence: 0.9,\n tags: ['local', service],\n metadata: { port, service, host: 'localhost' },\n });\n }\n return { nodes, edges: [] };\n },\n};\n","import { ScannerRegistry } from './types.js';\nimport { bookmarksScanner } from './bookmarks.js';\nimport { installedAppsScanner } from './installed-apps.js';\nimport { portsScanner } from './ports.js';\n\nexport { ScannerRegistry } from './types.js';\nexport type { Scanner, ScanContext, ScanResult } from './types.js';\nexport { bookmarksScanner } from './bookmarks.js';\nexport { installedAppsScanner } from './installed-apps.js';\nexport { portsScanner, extractListeningPorts } from './ports.js';\n\n/** A registry pre-loaded with the built-in deterministic scanners. */\nexport function defaultRegistry(): ScannerRegistry {\n return new ScannerRegistry()\n .register(bookmarksScanner)\n .register(installedAppsScanner)\n .register(portsScanner);\n}\n","/**\n * Deterministic, LLM-free local discovery.\n *\n * Runs every applicable scanner from a {@link ScannerRegistry}, deduplicates and\n * persists the resulting nodes/edges, and returns counts. This is what powers the\n * MCP `run_discovery` tool without requiring any model — the host LLM can then\n * enrich the catalog via the read tools. (The Claude-driven loop in agent.ts\n * remains available as the optional, richer turnkey path.)\n */\n\nimport type { CartographyDB } from '../db.js';\nimport type { DiscoveryNode, DiscoveryEdge } from '../types.js';\nimport { PLATFORM, run } from '../platform.js';\nimport { defaultRegistry, ScannerRegistry } from '../scanners/registry.js';\nimport type { ScanContext } from '../scanners/types.js';\n\nexport interface LocalDiscoveryOptions {\n hint?: string;\n registry?: ScannerRegistry;\n /** Called after each scanner with a short progress line. */\n onProgress?: (line: string) => void;\n}\n\nexport async function runLocalDiscovery(\n db: CartographyDB,\n sessionId: string,\n opts: LocalDiscoveryOptions = {},\n): Promise<{ nodes: number; edges: number; scanners: string[] }> {\n const registry = opts.registry ?? defaultRegistry();\n const ctx: ScanContext = { hint: opts.hint, platform: PLATFORM, run };\n\n const nodes = new Map<string, DiscoveryNode>();\n const edges: DiscoveryEdge[] = [];\n const ran: string[] = [];\n\n for (const scanner of registry.forPlatform(PLATFORM)) {\n try {\n if (!(await scanner.detect(ctx))) continue;\n const result = await scanner.scan(ctx);\n ran.push(scanner.id);\n for (const node of result.nodes) {\n // Keep the highest-confidence record on id collision.\n const prev = nodes.get(node.id);\n if (!prev || node.confidence > prev.confidence) nodes.set(node.id, node);\n }\n edges.push(...result.edges);\n opts.onProgress?.(`${scanner.title}: +${result.nodes.length} nodes`);\n } catch (err) {\n opts.onProgress?.(`${scanner.title}: failed (${err instanceof Error ? err.message : String(err)})`);\n }\n }\n\n for (const node of nodes.values()) db.upsertNode(sessionId, node);\n // Only persist edges whose endpoints exist.\n for (const edge of edges) {\n if (nodes.has(edge.sourceId) && nodes.has(edge.targetId)) db.insertEdge(sessionId, edge);\n }\n\n return { nodes: nodes.size, edges: edges.length, scanners: ran };\n}\n\n/** Adapter matching the MCP `DiscoveryFn` signature. */\nexport function localDiscoveryFn(registry?: ScannerRegistry) {\n return async (db: CartographyDB, sessionId: string, opts: { hint?: string }) => {\n const r = await runLocalDiscovery(db, sessionId, { hint: opts.hint, registry });\n return { nodes: r.nodes, edges: r.edges };\n };\n}\n","/**\n * Shared entry logic for launching the Cartography MCP server, used by both the\n * dedicated `cartography-mcp` binary and the `mcp` CLI sub-command.\n *\n * Wires in semantic search (lazy, falls back to lexical) and deterministic local\n * discovery (no LLM required). All logging goes to stderr so stdout stays a clean\n * MCP protocol channel.\n */\n\nimport { CartographyDB } from '../db.js';\nimport { defaultConfig } from '../types.js';\nimport { createMcpServer } from './server.js';\nimport type { SearchFn } from './server.js';\nimport { runStdio, runHttp } from './transports.js';\nimport { createSemanticSearch } from '../semantic/search.js';\nimport { localDiscoveryFn } from '../discovery/local.js';\n\nexport interface StartMcpOptions {\n dbPath?: string;\n session?: string | 'latest';\n /** `http` runs Streamable HTTP; otherwise stdio (default). */\n transport?: 'stdio' | 'http';\n port?: number;\n host?: string;\n /** Enable semantic (vector) search. Default true; degrades to lexical if unavailable. */\n semantic?: boolean;\n /** Logger (stderr). */\n log?: (msg: string) => void;\n}\n\nexport async function startMcp(opts: StartMcpOptions = {}): Promise<void> {\n const log = opts.log ?? ((m: string) => process.stderr.write(m + '\\n'));\n const db = new CartographyDB(opts.dbPath ?? defaultConfig().dbPath);\n\n let search: SearchFn | undefined;\n if (opts.semantic !== false) {\n search = await createSemanticSearch(db);\n log('semantic search: ready');\n }\n const discovery = localDiscoveryFn();\n\n const factory = () => createMcpServer({ db, session: opts.session ?? 'latest', search, discovery });\n\n if (opts.transport === 'http') {\n const port = opts.port ?? 3737;\n const host = opts.host ?? '127.0.0.1';\n await runHttp(factory, { port, host });\n log(`Cartography MCP server (Streamable HTTP) on http://${host}:${port}/mcp`);\n } else {\n log('Cartography MCP server (stdio) ready');\n await runStdio(factory());\n }\n}\n"],"mappings":"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","names":["z","z","body","lexicalSearch"]}