@datasynx/agentic-ai-cartography 2.4.0 → 2.6.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/dist/api-bin.js +2 -2
- package/dist/{chunk-X5JA2UDT.js → chunk-GA4427LB.js} +134 -14
- package/dist/chunk-GA4427LB.js.map +1 -0
- package/dist/{chunk-L4OSL7I6.js → chunk-PQ7Q6MI5.js} +130 -12
- package/dist/chunk-PQ7Q6MI5.js.map +1 -0
- package/dist/{chunk-B4QWX7CP.js → chunk-X3UWUX3G.js} +55 -11
- package/dist/chunk-X3UWUX3G.js.map +1 -0
- package/dist/cli.js +91 -33
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +363 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +262 -3
- package/dist/index.d.ts +262 -3
- package/dist/index.js +343 -58
- package/dist/index.js.map +1 -1
- package/dist/mcp-bin.js +2 -2
- package/package.json +1 -1
- package/server.json +2 -2
- package/dist/chunk-B4QWX7CP.js.map +0 -1
- package/dist/chunk-L4OSL7I6.js.map +0 -1
- package/dist/chunk-X5JA2UDT.js.map +0 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
AuthorizationError,
|
|
3
4
|
CartographyDB,
|
|
4
5
|
RulesetSchema,
|
|
6
|
+
SqliteCredentialStore,
|
|
5
7
|
assertSafeBind,
|
|
6
|
-
|
|
8
|
+
authorize,
|
|
9
|
+
bearerToken,
|
|
7
10
|
cloudAwsScanner,
|
|
8
11
|
cloudAzureScanner,
|
|
9
12
|
cloudGcpScanner,
|
|
@@ -17,10 +20,11 @@ import {
|
|
|
17
20
|
keyMetaOf,
|
|
18
21
|
normalizeTenant,
|
|
19
22
|
redactValue,
|
|
23
|
+
resolvePrincipal,
|
|
20
24
|
sanitizeUntrusted,
|
|
21
25
|
stableStringify,
|
|
22
26
|
stripSensitive
|
|
23
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-GA4427LB.js";
|
|
24
28
|
import {
|
|
25
29
|
EdgeSchema,
|
|
26
30
|
NODE_TYPES,
|
|
@@ -1534,7 +1538,7 @@ async function executeNlQuery(db, sessionId, search, intent, opts = {}) {
|
|
|
1534
1538
|
|
|
1535
1539
|
// src/mcp/server.ts
|
|
1536
1540
|
var SERVER_NAME = "cartography";
|
|
1537
|
-
var SERVER_VERSION = "2.
|
|
1541
|
+
var SERVER_VERSION = "2.6.0";
|
|
1538
1542
|
var SERVICE_TYPES = NODE_TYPE_GROUPS.web;
|
|
1539
1543
|
var DATA_TYPES = NODE_TYPE_GROUPS.data;
|
|
1540
1544
|
var lexicalSearch = async (db, sessionId, query, opts) => db.searchNodes(sessionId, query, { types: opts.types, limit: opts.limit }).map((node) => ({ node }));
|
|
@@ -1936,6 +1940,14 @@ function createMcpServer(opts = {}) {
|
|
|
1936
1940
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true }
|
|
1937
1941
|
},
|
|
1938
1942
|
async (args) => {
|
|
1943
|
+
if (opts.principal) {
|
|
1944
|
+
try {
|
|
1945
|
+
authorize(opts.principal, "discovery");
|
|
1946
|
+
} catch (err) {
|
|
1947
|
+
if (err instanceof AuthorizationError) return json({ error: `forbidden: role '${opts.principal.role}' may not run discovery (operator required)` });
|
|
1948
|
+
throw err;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1939
1951
|
let sid = resolveSession();
|
|
1940
1952
|
if (args.update) {
|
|
1941
1953
|
if (!sid) return json({ error: "No session to update; run discovery first." });
|
|
@@ -2035,6 +2047,9 @@ import { randomUUID } from "crypto";
|
|
|
2035
2047
|
import http from "http";
|
|
2036
2048
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2037
2049
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
2050
|
+
function samePrincipal(a, b) {
|
|
2051
|
+
return a.subject === b.subject && a.tenant === b.tenant && a.role === b.role;
|
|
2052
|
+
}
|
|
2038
2053
|
async function runStdio(server) {
|
|
2039
2054
|
const transport = new StdioServerTransport();
|
|
2040
2055
|
await server.connect(transport);
|
|
@@ -2079,6 +2094,14 @@ async function runHttp(factory, opts = {}) {
|
|
|
2079
2094
|
assertSafeBind({ host, port, ...opts.allowedHosts ? { allowedHosts: opts.allowedHosts } : {}, ...opts.token ? { token: opts.token } : {} });
|
|
2080
2095
|
const allowedHosts = opts.allowedHosts ?? defaultAllowedHosts(host, port);
|
|
2081
2096
|
const token = opts.token;
|
|
2097
|
+
const authStore = opts.auth?.store;
|
|
2098
|
+
const defaultTenant = opts.defaultTenant;
|
|
2099
|
+
const resolveAuth = (header) => resolvePrincipal(bearerToken(header), {
|
|
2100
|
+
...authStore ? { store: authStore } : {},
|
|
2101
|
+
...token ? { sharedToken: token } : {},
|
|
2102
|
+
...defaultTenant ? { defaultTenant } : {},
|
|
2103
|
+
...opts.auth?.required ? { required: true } : {}
|
|
2104
|
+
});
|
|
2082
2105
|
const transports = /* @__PURE__ */ new Map();
|
|
2083
2106
|
const httpServer = http.createServer(async (req, res) => {
|
|
2084
2107
|
try {
|
|
@@ -2088,7 +2111,8 @@ async function runHttp(factory, opts = {}) {
|
|
|
2088
2111
|
res.writeHead(404, { "content-type": "application/json" }).end('{"error":"not found"}');
|
|
2089
2112
|
return;
|
|
2090
2113
|
}
|
|
2091
|
-
|
|
2114
|
+
const principal = resolveAuth(req.headers["authorization"]);
|
|
2115
|
+
if (!principal) {
|
|
2092
2116
|
res.writeHead(401, { "content-type": "application/json", "www-authenticate": "Bearer" }).end('{"error":"unauthorized"}');
|
|
2093
2117
|
return;
|
|
2094
2118
|
}
|
|
@@ -2115,8 +2139,12 @@ async function runHttp(factory, opts = {}) {
|
|
|
2115
2139
|
const sessionId = req.headers["mcp-session-id"];
|
|
2116
2140
|
const existing = sessionId ? transports.get(sessionId) : void 0;
|
|
2117
2141
|
if (existing) {
|
|
2142
|
+
if (!samePrincipal(existing.principal, principal)) {
|
|
2143
|
+
res.writeHead(403, { "content-type": "application/json" }).end('{"error":"session belongs to a different principal"}');
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2118
2146
|
const body2 = req.method === "POST" ? await readJsonBody(req) : void 0;
|
|
2119
|
-
await existing.handleRequest(req, res, body2);
|
|
2147
|
+
await existing.transport.handleRequest(req, res, body2);
|
|
2120
2148
|
return;
|
|
2121
2149
|
}
|
|
2122
2150
|
if (req.method !== "POST") {
|
|
@@ -2130,13 +2158,13 @@ async function runHttp(factory, opts = {}) {
|
|
|
2130
2158
|
allowedHosts,
|
|
2131
2159
|
...opts.allowedOrigins ? { allowedOrigins: opts.allowedOrigins } : {},
|
|
2132
2160
|
onsessioninitialized: (id) => {
|
|
2133
|
-
transports.set(id, transport);
|
|
2161
|
+
transports.set(id, { transport, principal });
|
|
2134
2162
|
}
|
|
2135
2163
|
});
|
|
2136
2164
|
transport.onclose = () => {
|
|
2137
2165
|
if (transport.sessionId) transports.delete(transport.sessionId);
|
|
2138
2166
|
};
|
|
2139
|
-
await factory().connect(transport);
|
|
2167
|
+
await factory(principal).connect(transport);
|
|
2140
2168
|
await transport.handleRequest(req, res, body);
|
|
2141
2169
|
} catch (err) {
|
|
2142
2170
|
process.stderr.write(`[cartography-mcp] HTTP request failed: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -2558,7 +2586,8 @@ function parseMcpArgs(argv) {
|
|
|
2558
2586
|
else if (a === "--anon-mode") {
|
|
2559
2587
|
const m = argv[++i];
|
|
2560
2588
|
if (m === "reject" || m === "strip") opts.anonMode = m;
|
|
2561
|
-
} else if (a === "--
|
|
2589
|
+
} else if (a === "--auth-required") opts.authRequired = true;
|
|
2590
|
+
else if (a === "--help" || a === "-h") opts.help = true;
|
|
2562
2591
|
}
|
|
2563
2592
|
return opts;
|
|
2564
2593
|
}
|
|
@@ -2573,8 +2602,21 @@ async function startMcp(opts = {}) {
|
|
|
2573
2602
|
const discovery = localDiscoveryFn(void 0, plugins);
|
|
2574
2603
|
const tenant = normalizeTenant(opts.tenant);
|
|
2575
2604
|
const serverMode = opts.serverMode === true;
|
|
2576
|
-
const
|
|
2577
|
-
const
|
|
2605
|
+
const authStore = new SqliteCredentialStore(db);
|
|
2606
|
+
const rbacActive = authStore.count() > 0;
|
|
2607
|
+
const factory = (principal) => {
|
|
2608
|
+
const scopeTenant = rbacActive && principal ? principal.tenant : tenant;
|
|
2609
|
+
const orgArg = serverMode ? scopeTenant : void 0;
|
|
2610
|
+
return createMcpServer({
|
|
2611
|
+
db,
|
|
2612
|
+
session: opts.session ?? "latest",
|
|
2613
|
+
tenant: scopeTenant,
|
|
2614
|
+
search,
|
|
2615
|
+
discovery,
|
|
2616
|
+
...principal ? { principal } : {},
|
|
2617
|
+
...orgArg !== void 0 ? { org: orgArg } : {}
|
|
2618
|
+
});
|
|
2619
|
+
};
|
|
2578
2620
|
const transport = serverMode ? "http" : opts.transport;
|
|
2579
2621
|
if (transport === "http") {
|
|
2580
2622
|
const port = opts.port ?? 3737;
|
|
@@ -2589,6 +2631,8 @@ async function startMcp(opts = {}) {
|
|
|
2589
2631
|
await runHttp(factory, {
|
|
2590
2632
|
port,
|
|
2591
2633
|
host,
|
|
2634
|
+
auth: { store: authStore, ...opts.authRequired ? { required: true } : {} },
|
|
2635
|
+
defaultTenant: tenant,
|
|
2592
2636
|
...opts.allowedHosts ? { allowedHosts: opts.allowedHosts } : {},
|
|
2593
2637
|
...token ? { token } : {},
|
|
2594
2638
|
...onIngest ? { onIngest } : {}
|
|
@@ -2615,4 +2659,4 @@ export {
|
|
|
2615
2659
|
parseMcpArgs,
|
|
2616
2660
|
startMcp
|
|
2617
2661
|
};
|
|
2618
|
-
//# sourceMappingURL=chunk-
|
|
2662
|
+
//# sourceMappingURL=chunk-X3UWUX3G.js.map
|