@datasynx/agentic-ai-cartography 2.0.0 → 2.3.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/AGENTS.md +32 -0
- package/README.md +115 -6
- package/dist/api-bin.js +24 -0
- package/dist/api-bin.js.map +1 -0
- package/dist/{bookmarks-VS56KVCO.js → bookmarks-WXHE7GN7.js} +6 -3
- package/dist/{chunk-CJ2PITFA.js → chunk-2SZ5QHGH.js} +71 -9
- package/dist/chunk-2SZ5QHGH.js.map +1 -0
- package/dist/chunk-7QEBFMN4.js +3278 -0
- package/dist/chunk-7QEBFMN4.js.map +1 -0
- package/dist/chunk-7VZH5PFV.js +1134 -0
- package/dist/chunk-7VZH5PFV.js.map +1 -0
- package/dist/chunk-B2AKONVW.js +2465 -0
- package/dist/chunk-B2AKONVW.js.map +1 -0
- package/dist/chunk-WCR47QA2.js +277 -0
- package/dist/chunk-WCR47QA2.js.map +1 -0
- package/dist/cli.js +2367 -663
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +9405 -57913
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3048 -69
- package/dist/index.d.ts +3048 -69
- package/dist/index.js +9150 -2607
- package/dist/index.js.map +1 -1
- package/dist/mcp-bin.js +17 -26
- package/dist/mcp-bin.js.map +1 -1
- package/dist/types-TJWXAQ2L.js +66 -0
- package/llms-full.txt +758 -0
- package/llms.txt +24 -0
- package/package.json +27 -9
- package/scripts/build-llms.mjs +89 -0
- package/scripts/build-mcpb.mjs +31 -0
- package/scripts/gen-api-schemas.ts +29 -0
- package/scripts/gen-docs.ts +123 -0
- package/scripts/sync-version.mjs +51 -0
- package/scripts/validate-server-json.mjs +54 -0
- package/server.json +4 -4
- package/dist/chunk-CJ2PITFA.js.map +0 -1
- package/dist/chunk-D6SRSLBF.js +0 -48
- package/dist/chunk-J6FDZ6HZ.js +0 -142
- package/dist/chunk-J6FDZ6HZ.js.map +0 -1
- package/dist/chunk-UGSNG3QJ.js +0 -49
- package/dist/chunk-UGSNG3QJ.js.map +0 -1
- package/dist/chunk-W7YE6AAH.js +0 -1516
- package/dist/chunk-W7YE6AAH.js.map +0 -1
- 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 +0 -12294
- package/dist/sdk-A6NLO3DJ.js.map +0 -1
- package/dist/sdk-G5D4WQZ4.js +0 -12293
- package/dist/sdk-G5D4WQZ4.js.map +0 -1
- package/dist/sdk-QSTAREST.js +0 -4869
- package/dist/sdk-QSTAREST.js.map +0 -1
- package/dist/sqlite-vec-EZN67B2V.js +0 -40
- package/dist/sqlite-vec-EZN67B2V.js.map +0 -1
- package/dist/sqlite-vec-UK5YYE5T.js +0 -39
- package/dist/sqlite-vec-UK5YYE5T.js.map +0 -1
- package/dist/transformers.node-BTYUTJK5.js +0 -42884
- package/dist/transformers.node-BTYUTJK5.js.map +0 -1
- package/dist/transformers.node-J6PRTTOX.js +0 -42883
- package/dist/transformers.node-J6PRTTOX.js.map +0 -1
- package/dist/types-JG27FR3E.js +0 -29
- package/dist/types-JG27FR3E.js.map +0 -1
- package/scripts/postinstall.mjs +0 -7
- /package/dist/{bookmarks-VS56KVCO.js.map → bookmarks-WXHE7GN7.js.map} +0 -0
- /package/dist/{chunk-D6SRSLBF.js.map → types-TJWXAQ2L.js.map} +0 -0
package/llms.txt
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @datasynx/agentic-ai-cartography
|
|
2
|
+
|
|
3
|
+
> MCP-first infrastructure & agentic-AI cartography — install once, every AI agent knows your system landscape. Read-only discovery exposed over the Model Context Protocol.
|
|
4
|
+
|
|
5
|
+
Cartography discovers your services, databases, SaaS tools and dependencies
|
|
6
|
+
(read-only, deterministic) and exposes the topology over the Model Context
|
|
7
|
+
Protocol. Install once and any MCP host or agent framework can query it.
|
|
8
|
+
|
|
9
|
+
## Getting started
|
|
10
|
+
|
|
11
|
+
- [Quickstart](https://datasynx.github.io/agentic-ai-cartography/#quickstart): From zero to an agent that knows your system.
|
|
12
|
+
- [Install into a client](https://datasynx.github.io/agentic-ai-cartography/#install): Write the MCP config for any supported host.
|
|
13
|
+
|
|
14
|
+
## Reference
|
|
15
|
+
|
|
16
|
+
- [MCP tools & resources](https://datasynx.github.io/agentic-ai-cartography/#tools): Resources, tools and prompts the server exposes.
|
|
17
|
+
- [CLI](https://datasynx.github.io/agentic-ai-cartography/#cli): datasynx-cartography commands and flags.
|
|
18
|
+
- [Supported clients](https://datasynx.github.io/agentic-ai-cartography/#clients): The host install matrix.
|
|
19
|
+
- [Non-MCP frameworks](https://datasynx.github.io/agentic-ai-cartography/#adapters): LangGraph, CrewAI, Vercel AI SDK and more.
|
|
20
|
+
|
|
21
|
+
## Explanation
|
|
22
|
+
|
|
23
|
+
- [Why MCP-first](https://datasynx.github.io/agentic-ai-cartography/#architecture): The design rationale.
|
|
24
|
+
- [Threat model](https://github.com/datasynx/agentic-ai-cartography/blob/main/docs/explanation/threat-model.md): Attacker model, trust boundaries and mitigations.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datasynx/agentic-ai-cartography",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "MCP-first infrastructure & agentic-AI cartography — install once, every AI agent knows your system landscape. Read-only discovery exposed over the Model Context Protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"bin": {
|
|
12
12
|
"datasynx-cartography": "./dist/cli.js",
|
|
13
|
-
"cartography-mcp": "./dist/mcp-bin.js"
|
|
13
|
+
"cartography-mcp": "./dist/mcp-bin.js",
|
|
14
|
+
"cartography-api": "./dist/api-bin.js"
|
|
14
15
|
},
|
|
15
16
|
"exports": {
|
|
16
17
|
".": {
|
|
@@ -30,19 +31,26 @@
|
|
|
30
31
|
"scripts",
|
|
31
32
|
"server.json",
|
|
32
33
|
"README.md",
|
|
33
|
-
"
|
|
34
|
+
"AGENTS.md",
|
|
35
|
+
"LICENSE",
|
|
36
|
+
"llms.txt",
|
|
37
|
+
"llms-full.txt"
|
|
34
38
|
],
|
|
35
39
|
"scripts": {
|
|
36
40
|
"build": "tsup",
|
|
41
|
+
"build:mcpb": "node scripts/build-mcpb.mjs",
|
|
37
42
|
"dev": "tsx src/cli.ts",
|
|
38
43
|
"test": "vitest run",
|
|
39
44
|
"test:watch": "vitest",
|
|
40
45
|
"test:coverage": "vitest run --coverage",
|
|
46
|
+
"docs:llms": "node scripts/build-llms.mjs",
|
|
47
|
+
"docs:tables": "tsx scripts/gen-docs.ts",
|
|
48
|
+
"docs:api": "tsx scripts/gen-api-schemas.ts",
|
|
49
|
+
"docs:build": "npm run docs:tables && npm run docs:llms && npm run docs:api",
|
|
41
50
|
"lint": "tsc --noEmit",
|
|
42
51
|
"typecheck": "tsc --noEmit",
|
|
43
52
|
"release": "semantic-release",
|
|
44
|
-
"prepublishOnly": "npm run lint && npm run test && npm run build"
|
|
45
|
-
"postinstall": "node scripts/postinstall.mjs"
|
|
53
|
+
"prepublishOnly": "npm run lint && npm run test && npm run build"
|
|
46
54
|
},
|
|
47
55
|
"engines": {
|
|
48
56
|
"node": ">=20.0.0"
|
|
@@ -81,27 +89,37 @@
|
|
|
81
89
|
"provenance": true
|
|
82
90
|
},
|
|
83
91
|
"license": "MIT",
|
|
92
|
+
"overrides": {
|
|
93
|
+
"tmp": "^0.2.7",
|
|
94
|
+
"hono": "^4.12.25"
|
|
95
|
+
},
|
|
84
96
|
"dependencies": {
|
|
85
97
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
86
|
-
"better-sqlite3": "^12.
|
|
98
|
+
"better-sqlite3": "^12.10.0",
|
|
87
99
|
"commander": "^14.0.0",
|
|
88
|
-
"
|
|
100
|
+
"smol-toml": "^1.6.1",
|
|
101
|
+
"yaml": "^2.9.0",
|
|
102
|
+
"zod": "^4.4.3"
|
|
89
103
|
},
|
|
90
104
|
"optionalDependencies": {
|
|
91
|
-
"@anthropic-ai/claude-agent-sdk": "
|
|
92
|
-
"@anthropic-ai/sdk": "^0.
|
|
105
|
+
"@anthropic-ai/claude-agent-sdk": ">=0.2.70 <0.4.0",
|
|
106
|
+
"@anthropic-ai/sdk": "^0.104.0",
|
|
93
107
|
"@huggingface/transformers": "^4.2.0",
|
|
108
|
+
"openai": "^6.44.0",
|
|
94
109
|
"sqlite-vec": "^0.1.9"
|
|
95
110
|
},
|
|
96
111
|
"devDependencies": {
|
|
112
|
+
"@anthropic-ai/mcpb": "^2.1.2",
|
|
97
113
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
98
114
|
"@semantic-release/changelog": "^6.0.3",
|
|
115
|
+
"@semantic-release/exec": "^7.1.0",
|
|
99
116
|
"@semantic-release/git": "^10.0.1",
|
|
100
117
|
"@semantic-release/github": "^11.0.1",
|
|
101
118
|
"@semantic-release/npm": "^12.0.1",
|
|
102
119
|
"@types/better-sqlite3": "^7.6.12",
|
|
103
120
|
"@types/node": "^22.10.0",
|
|
104
121
|
"@vitest/coverage-v8": "^4.1.0",
|
|
122
|
+
"ajv": "^8.20.0",
|
|
105
123
|
"license-checker": "^25.0.1",
|
|
106
124
|
"publint": "^0.3.0",
|
|
107
125
|
"semantic-release": "^24.2.0",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate llms.txt (a curated, LLM-friendly navigation map) and llms-full.txt
|
|
4
|
+
* (the full documentation text in one file) from the docs/ sources, per the
|
|
5
|
+
* llmstxt.org convention. Canonical output lives at the repo root so the files
|
|
6
|
+
* ship in the npm package and are agent-discoverable; `docs:build` also copies
|
|
7
|
+
* them into docs/public so the site serves them at its domain root.
|
|
8
|
+
*
|
|
9
|
+
* Run via `npm run docs:llms`. Kept in lockstep with the docs by a drift test.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'node:fs';
|
|
13
|
+
import { resolve, dirname } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
|
|
16
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
17
|
+
const SITE = 'https://datasynx.github.io/agentic-ai-cartography';
|
|
18
|
+
|
|
19
|
+
/** Curated documentation index. Links point to anchors on the single-page site. */
|
|
20
|
+
const SECTIONS = [
|
|
21
|
+
{
|
|
22
|
+
heading: 'Getting started',
|
|
23
|
+
pages: [
|
|
24
|
+
{ file: 'docs/tutorials/index.md', url: `${SITE}/#quickstart`, title: 'Quickstart', desc: 'From zero to an agent that knows your system.' },
|
|
25
|
+
{ file: 'docs/how-to/install.md', url: `${SITE}/#install`, title: 'Install into a client', desc: 'Write the MCP config for any supported host.' },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
heading: 'Reference',
|
|
30
|
+
pages: [
|
|
31
|
+
{ file: 'docs/reference/mcp.md', url: `${SITE}/#tools`, title: 'MCP tools & resources', desc: 'Resources, tools and prompts the server exposes.' },
|
|
32
|
+
{ file: 'docs/reference/cli.md', url: `${SITE}/#cli`, title: 'CLI', desc: 'datasynx-cartography commands and flags.' },
|
|
33
|
+
{ file: 'docs/reference/clients.md', url: `${SITE}/#clients`, title: 'Supported clients', desc: 'The host install matrix.' },
|
|
34
|
+
{ file: 'docs/adapters.md', url: `${SITE}/#adapters`, title: 'Non-MCP frameworks', desc: 'LangGraph, CrewAI, Vercel AI SDK and more.' },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
heading: 'Explanation',
|
|
39
|
+
pages: [
|
|
40
|
+
{ file: 'docs/explanation/index.md', url: `${SITE}/#architecture`, title: 'Why MCP-first', desc: 'The design rationale.' },
|
|
41
|
+
{ file: 'docs/explanation/threat-model.md', url: 'https://github.com/datasynx/agentic-ai-cartography/blob/main/docs/explanation/threat-model.md', title: 'Threat model', desc: 'Attacker model, trust boundaries and mitigations.' },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const stripFrontmatter = (s) => s.replace(/^---\n[\s\S]*?\n---\n/, '');
|
|
47
|
+
|
|
48
|
+
/** Pure: build both files' contents from the docs sources. Side-effect free. */
|
|
49
|
+
export function generate() {
|
|
50
|
+
const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
|
|
51
|
+
const SUMMARY = pkg.description;
|
|
52
|
+
|
|
53
|
+
const llms = [`# ${pkg.name}`, '', `> ${SUMMARY}`, ''];
|
|
54
|
+
llms.push(
|
|
55
|
+
'Cartography discovers your services, databases, SaaS tools and dependencies',
|
|
56
|
+
'(read-only, deterministic) and exposes the topology over the Model Context',
|
|
57
|
+
'Protocol. Install once and any MCP host or agent framework can query it.',
|
|
58
|
+
'',
|
|
59
|
+
);
|
|
60
|
+
for (const section of SECTIONS) {
|
|
61
|
+
llms.push(`## ${section.heading}`, '');
|
|
62
|
+
for (const p of section.pages) llms.push(`- [${p.title}](${p.url}): ${p.desc}`);
|
|
63
|
+
llms.push('');
|
|
64
|
+
}
|
|
65
|
+
const llmsTxt = llms.join('\n');
|
|
66
|
+
|
|
67
|
+
const full = [`# ${pkg.name} — full documentation`, '', `> ${SUMMARY}`, ''];
|
|
68
|
+
for (const section of SECTIONS) {
|
|
69
|
+
for (const p of section.pages) {
|
|
70
|
+
full.push('', '---', '', `<!-- source: ${p.file} -->`, '', stripFrontmatter(readFileSync(resolve(root, p.file), 'utf8')).trim(), '');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const llmsFullTxt = full.join('\n') + '\n';
|
|
74
|
+
return { llmsTxt, llmsFullTxt };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Write the canonical root files and mirror them into docs/ so Pages serves them at its root. */
|
|
78
|
+
export function write() {
|
|
79
|
+
const { llmsTxt, llmsFullTxt } = generate();
|
|
80
|
+
writeFileSync(resolve(root, 'llms.txt'), llmsTxt);
|
|
81
|
+
writeFileSync(resolve(root, 'llms-full.txt'), llmsFullTxt);
|
|
82
|
+
copyFileSync(resolve(root, 'llms.txt'), resolve(root, 'docs', 'llms.txt'));
|
|
83
|
+
copyFileSync(resolve(root, 'llms-full.txt'), resolve(root, 'docs', 'llms-full.txt'));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
87
|
+
write();
|
|
88
|
+
console.log('✓ Wrote llms.txt and llms-full.txt (+ docs/public mirror)');
|
|
89
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Build the Claude Desktop one-click bundle: keep `mcpb/manifest.json` in sync
|
|
4
|
+
* with package.json's version, then pack `mcpb/` into `dist/cartography.mcpb`
|
|
5
|
+
* using the official @anthropic-ai/mcpb CLI.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
9
|
+
import { execFileSync } from 'node:child_process';
|
|
10
|
+
import { dirname, resolve } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
14
|
+
const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
|
|
15
|
+
const manifestPath = resolve(root, 'mcpb', 'manifest.json');
|
|
16
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
17
|
+
|
|
18
|
+
// Single source of truth: the npm version drives the manifest version.
|
|
19
|
+
if (manifest.version !== pkg.version) {
|
|
20
|
+
manifest.version = pkg.version;
|
|
21
|
+
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
|
|
22
|
+
console.log(`Synced manifest version → ${pkg.version}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
mkdirSync(resolve(root, 'dist'), { recursive: true });
|
|
26
|
+
const out = resolve(root, 'dist', 'cartography.mcpb');
|
|
27
|
+
|
|
28
|
+
const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
29
|
+
execFileSync(npx, ['mcpb', 'validate', manifestPath], { stdio: 'inherit', cwd: root });
|
|
30
|
+
execFileSync(npx, ['mcpb', 'pack', resolve(root, 'mcpb'), out], { stdio: 'inherit', cwd: root });
|
|
31
|
+
console.log(`\n✓ Wrote ${out}`);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Regenerate the committed API contract artifacts from the zod schemas / SDL:
|
|
4
|
+
* - docs/api/openapi.json (OpenAPI 3.1, from src/api/openapi.ts)
|
|
5
|
+
* - docs/api/schema.graphql (GraphQL SDL, from src/api/graphql.ts)
|
|
6
|
+
*
|
|
7
|
+
* Run via `npm run docs:api`. A test (`test/openapi.test.ts` / `test/api-graphql.test.ts`)
|
|
8
|
+
* asserts the in-memory build deep-equals these files, so they can never drift from
|
|
9
|
+
* what the server serves. The embedded OpenAPI `info.version` is kept in lockstep with
|
|
10
|
+
* package.json by scripts/sync-version.mjs on release.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
import { dirname, resolve } from 'node:path';
|
|
16
|
+
import { buildOpenApiDocument } from '../src/api/openapi.js';
|
|
17
|
+
import { SDL } from '../src/api/graphql.js';
|
|
18
|
+
|
|
19
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
20
|
+
const version = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8')).version as string;
|
|
21
|
+
|
|
22
|
+
const outDir = resolve(root, 'docs/api');
|
|
23
|
+
mkdirSync(outDir, { recursive: true });
|
|
24
|
+
|
|
25
|
+
const openapi = buildOpenApiDocument({ version });
|
|
26
|
+
writeFileSync(resolve(outDir, 'openapi.json'), JSON.stringify(openapi, null, 2) + '\n');
|
|
27
|
+
writeFileSync(resolve(outDir, 'schema.graphql'), SDL.endsWith('\n') ? SDL : SDL + '\n');
|
|
28
|
+
|
|
29
|
+
console.error(`gen-api-schemas: wrote docs/api/openapi.json (v${version}) + docs/api/schema.graphql`);
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regenerate the auto-generated documentation blocks from the single source of
|
|
3
|
+
* truth (the code), so the tool table and client matrix can never drift:
|
|
4
|
+
*
|
|
5
|
+
* - docs/reference/mcp.md → AUTO-GENERATED:tools (live MCP tool list)
|
|
6
|
+
* - docs/reference/clients.md → AUTO-GENERATED:clients (registry matrix)
|
|
7
|
+
* → AUTO-GENERATED:quickstarts (per-host config block)
|
|
8
|
+
* - AGENTS.md → the standard config block for agent context
|
|
9
|
+
*
|
|
10
|
+
* Run via `npm run docs:tables`. Guarded against drift by a test.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
14
|
+
import { resolve } from 'node:path';
|
|
15
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
16
|
+
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
|
|
17
|
+
import { createMcpServer } from '../src/mcp/server.js';
|
|
18
|
+
import { CartographyDB } from '../src/db.js';
|
|
19
|
+
import { defaultConfig } from '../src/types.js';
|
|
20
|
+
import { listClients, getClient, planInstall, defaultServerEntry } from '../src/installer/index.js';
|
|
21
|
+
import type { ResolveContext } from '../src/installer/index.js';
|
|
22
|
+
|
|
23
|
+
const root = resolve(import.meta.dirname, '..');
|
|
24
|
+
|
|
25
|
+
function replaceBlock(content: string, name: string, body: string): string {
|
|
26
|
+
const re = new RegExp(`(<!-- AUTO-GENERATED:${name} START[^\\n]*-->\\n)[\\s\\S]*?(<!-- AUTO-GENERATED:${name} END -->)`);
|
|
27
|
+
if (!re.test(content)) throw new Error(`marker ${name} not found`);
|
|
28
|
+
return content.replace(re, `$1${body}\n$2`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Live tool list from the running MCP server (single source of truth). */
|
|
32
|
+
async function toolTable(): Promise<string> {
|
|
33
|
+
const db = new CartographyDB(':memory:');
|
|
34
|
+
db.createSession('discover', defaultConfig());
|
|
35
|
+
const server = createMcpServer({ db, discovery: async () => ({ nodes: 0, edges: 0 }) });
|
|
36
|
+
const [ct, st] = InMemoryTransport.createLinkedPair();
|
|
37
|
+
const client = new Client({ name: 'gen-docs', version: '1.0.0' });
|
|
38
|
+
await Promise.all([client.connect(ct), server.connect(st)]);
|
|
39
|
+
const { tools } = await client.listTools();
|
|
40
|
+
await client.close();
|
|
41
|
+
db.close();
|
|
42
|
+
const rows = tools
|
|
43
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
44
|
+
.map((t) => `| \`${t.name}\` | ${t.annotations?.readOnlyHint ? '✅' : '—'} | ${(t.description ?? '').split('\n')[0]} |`);
|
|
45
|
+
return ['| Tool | Read-only | Description |', '| --- | --- | --- |', ...rows].join('\n');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function clientMatrix(): string {
|
|
49
|
+
const rows = listClients().map((c) => `| \`${c.id}\` | ${c.label} | ${c.format} | ${c.note ?? ''} |`);
|
|
50
|
+
return ['| id | Host | Format | Notes |', '| --- | --- | --- | --- |', ...rows].join('\n');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function quickstarts(): string {
|
|
54
|
+
const ctx: ResolveContext = { scope: 'global', os: 'linux', home: '~', cwd: '.', env: {} };
|
|
55
|
+
const entry = defaultServerEntry();
|
|
56
|
+
const out: string[] = [];
|
|
57
|
+
for (const c of listClients()) {
|
|
58
|
+
const spec = getClient(c.id)!;
|
|
59
|
+
const plan = planInstall(spec, ctx, { entry });
|
|
60
|
+
const lang = plan.format === 'json' ? 'json' : plan.format;
|
|
61
|
+
out.push(`### ${c.label} (\`${c.id}\`)`, '', `\`${plan.path}\``, '', '```' + lang, plan.after.trim(), '```', '');
|
|
62
|
+
}
|
|
63
|
+
return out.join('\n');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function agentsMd(): string {
|
|
67
|
+
const entry = defaultServerEntry();
|
|
68
|
+
const block = JSON.stringify({ mcpServers: { cartography: { command: entry.command, args: entry.args } } }, null, 2);
|
|
69
|
+
return `# Working with Cartography
|
|
70
|
+
|
|
71
|
+
This project can use **Cartography** — an MCP server that maps the system landscape
|
|
72
|
+
(services, datastores, SaaS tools, dependencies) read-only.
|
|
73
|
+
|
|
74
|
+
## Enable it
|
|
75
|
+
|
|
76
|
+
\`\`\`json
|
|
77
|
+
${block}
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
Or run \`datasynx-cartography install --client <id>\` (see \`list-clients\`).
|
|
81
|
+
|
|
82
|
+
## Use it
|
|
83
|
+
|
|
84
|
+
- Read \`cartography://graph/summary\` first — a low-token overview.
|
|
85
|
+
- Then drill in with \`query_infrastructure\`, \`get_dependencies\`, \`get_node\`.
|
|
86
|
+
- All tools are read-only; run \`run_discovery\` to (re)scan the local system.
|
|
87
|
+
|
|
88
|
+
<!-- Generated by \`npm run docs:tables\`; edit scripts/gen-docs.ts, not this file. -->
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface GeneratedDocs {
|
|
93
|
+
mcpPath: string;
|
|
94
|
+
mcp: string;
|
|
95
|
+
clientsPath: string;
|
|
96
|
+
clients: string;
|
|
97
|
+
agentsPath: string;
|
|
98
|
+
agents: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Pure: compute the regenerated file contents from the current sources. */
|
|
102
|
+
export async function buildDocs(): Promise<GeneratedDocs> {
|
|
103
|
+
const mcpPath = resolve(root, 'docs/reference/mcp.md');
|
|
104
|
+
const mcp = replaceBlock(readFileSync(mcpPath, 'utf8'), 'tools', await toolTable());
|
|
105
|
+
|
|
106
|
+
const clientsPath = resolve(root, 'docs/reference/clients.md');
|
|
107
|
+
let clients = readFileSync(clientsPath, 'utf8');
|
|
108
|
+
clients = replaceBlock(clients, 'clients', clientMatrix());
|
|
109
|
+
clients = replaceBlock(clients, 'quickstarts', quickstarts());
|
|
110
|
+
|
|
111
|
+
return { mcpPath, mcp, clientsPath, clients, agentsPath: resolve(root, 'AGENTS.md'), agents: agentsMd() };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function generateDocs(): Promise<void> {
|
|
115
|
+
const d = await buildDocs();
|
|
116
|
+
writeFileSync(d.mcpPath, d.mcp);
|
|
117
|
+
writeFileSync(d.clientsPath, d.clients);
|
|
118
|
+
writeFileSync(d.agentsPath, d.agents);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
122
|
+
generateDocs().then(() => console.log('✓ Regenerated tool table, client matrix, quickstarts, AGENTS.md'));
|
|
123
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Propagate a release version to every non-package.json site that carries it.
|
|
3
|
+
// @semantic-release/npm already bumps package.json + package-lock.json; this
|
|
4
|
+
// script keeps the MCP registry manifest, the .mcpb manifest, the Claude Code
|
|
5
|
+
// plugin manifest, and the hard-coded MCP SERVER_VERSION in lockstep. Run by
|
|
6
|
+
// the @semantic-release/exec prepare step as: node scripts/sync-version.mjs <version>
|
|
7
|
+
// Falls back to package.json's version when no argument is given (manual use).
|
|
8
|
+
//
|
|
9
|
+
// Edits are raw-text regex replacements (not JSON re-serialization) so the
|
|
10
|
+
// existing hand-authored formatting of server.json / manifest.json is preserved
|
|
11
|
+
// byte-for-byte except the version literals.
|
|
12
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { dirname, resolve } from 'node:path';
|
|
15
|
+
|
|
16
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
17
|
+
const version =
|
|
18
|
+
process.argv[2] ?? JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8')).version;
|
|
19
|
+
|
|
20
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
21
|
+
console.error(`sync-version: refusing to write invalid version "${version}"`);
|
|
22
|
+
throw new Error(`invalid version: ${version}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Replace every match of `pattern` in `relPath` with `replacement`; require ≥1 hit. */
|
|
26
|
+
const editFile = (relPath, pattern, replacement) => {
|
|
27
|
+
const path = resolve(root, relPath);
|
|
28
|
+
const before = readFileSync(path, 'utf8');
|
|
29
|
+
let hits = 0;
|
|
30
|
+
const after = before.replace(pattern, (m) => {
|
|
31
|
+
hits += 1;
|
|
32
|
+
return replacement(m);
|
|
33
|
+
});
|
|
34
|
+
if (hits === 0) {
|
|
35
|
+
throw new Error(`sync-version: no version marker matched in ${relPath}`);
|
|
36
|
+
}
|
|
37
|
+
if (after !== before) writeFileSync(path, after);
|
|
38
|
+
console.error(`sync-version: ${relPath} -> ${version} (${hits} site${hits === 1 ? '' : 's'})`);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// `"version": "..."` — leading quote excludes `"manifest_version"`. Matches both
|
|
42
|
+
// the top-level and packages[].version in server.json (intentionally kept equal).
|
|
43
|
+
const jsonVersion = /"version":(\s*)"[^"]*"/g;
|
|
44
|
+
const toJson = (m) => m.replace(/"[^"]*"$/, `"${version}"`);
|
|
45
|
+
|
|
46
|
+
editFile('server.json', jsonVersion, toJson);
|
|
47
|
+
editFile('mcpb/manifest.json', jsonVersion, toJson);
|
|
48
|
+
editFile('plugin/.claude-plugin/plugin.json', jsonVersion, toJson);
|
|
49
|
+
editFile('src/mcp/server.ts', /const SERVER_VERSION = '[^']*';/, () => `const SERVER_VERSION = '${version}';`);
|
|
50
|
+
// API server (4.2): the only `"version"` site in the generated OpenAPI doc is info.version.
|
|
51
|
+
editFile('docs/api/openapi.json', jsonVersion, toJson);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Validate server.json before it ships:
|
|
3
|
+
// (1) version parity with package.json [hard fail]
|
|
4
|
+
// (2) required-field structure [hard fail]
|
|
5
|
+
// (3) JSON-schema validation against $schema [hard on real violations,
|
|
6
|
+
// warn-and-skip on network/$ref errors so CI never flakes]
|
|
7
|
+
// Authoritative schema validation also runs at publish time via mcp-publisher
|
|
8
|
+
// (.github/workflows/mcp-publish.yml).
|
|
9
|
+
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { resolve, dirname } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
|
|
14
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
15
|
+
const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
|
|
16
|
+
const server = JSON.parse(readFileSync(resolve(root, 'server.json'), 'utf8'));
|
|
17
|
+
|
|
18
|
+
const fail = (m) => { console.error(`::error::${m}`); process.exitCode = 1; };
|
|
19
|
+
|
|
20
|
+
// (1) version parity
|
|
21
|
+
if (server.version !== pkg.version) {
|
|
22
|
+
fail(`server.json version (${server.version}) != package.json version (${pkg.version})`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// (2) required structure
|
|
26
|
+
for (const key of ['$schema', 'name', 'version', 'packages']) {
|
|
27
|
+
if (server[key] === undefined) fail(`server.json missing required field: ${key}`);
|
|
28
|
+
}
|
|
29
|
+
if (Array.isArray(server.packages)) {
|
|
30
|
+
server.packages.forEach((p, i) => {
|
|
31
|
+
for (const k of ['identifier', 'version', 'transport']) {
|
|
32
|
+
if (p[k] === undefined) fail(`server.json packages[${i}] missing: ${k}`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
} else if (server.packages !== undefined) {
|
|
36
|
+
fail('server.json packages must be an array');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// (3) best-effort schema validation
|
|
40
|
+
try {
|
|
41
|
+
const { default: Ajv } = await import('ajv');
|
|
42
|
+
const res = await fetch(server.$schema, { signal: AbortSignal.timeout(10_000) });
|
|
43
|
+
if (!res.ok) throw new Error(`schema fetch ${res.status}`);
|
|
44
|
+
const schema = await res.json();
|
|
45
|
+
const ajv = new Ajv({ strict: false, allErrors: true, validateFormats: false });
|
|
46
|
+
const validate = ajv.compile(schema);
|
|
47
|
+
if (!validate(server)) {
|
|
48
|
+
for (const e of validate.errors ?? []) fail(`schema: ${e.instancePath || '/'} ${e.message}`);
|
|
49
|
+
}
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.warn(`::warning::Skipped remote schema validation (${err instanceof Error ? err.message : String(err)}); parity + structure checks still enforced.`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!process.exitCode) console.log(`server.json OK — version parity + structure (${pkg.version})`);
|
package/server.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.datasynx/cartography",
|
|
4
|
-
"description": "MCP-first
|
|
5
|
-
"version": "2.
|
|
4
|
+
"description": "MCP-first read-only discovery of your infra & SaaS landscape as MCP resources, tools and prompts.",
|
|
5
|
+
"version": "2.3.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/datasynx/agentic-ai-cartography",
|
|
8
8
|
"source": "github"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
14
14
|
"identifier": "@datasynx/agentic-ai-cartography",
|
|
15
|
-
"version": "2.
|
|
15
|
+
"version": "2.3.0",
|
|
16
16
|
"runtimeHint": "npx",
|
|
17
17
|
"transport": { "type": "stdio" },
|
|
18
18
|
"runtimeArguments": [
|