@cocaxcode/ai-context-inspector 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -0
- package/dist/chunk-6HBCUZQJ.js +1565 -0
- package/dist/index.js +112 -0
- package/dist/server-6EILEUO5.js +177 -0
- package/package.json +74 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
generateHtml,
|
|
4
|
+
runAllScanners
|
|
5
|
+
} from "./chunk-6HBCUZQJ.js";
|
|
6
|
+
|
|
7
|
+
// src/cli.ts
|
|
8
|
+
import { parseArgs } from "util";
|
|
9
|
+
import { access, mkdir, writeFile } from "fs/promises";
|
|
10
|
+
import { dirname, resolve } from "path";
|
|
11
|
+
function parseCliArgs(argv) {
|
|
12
|
+
const { values } = parseArgs({
|
|
13
|
+
args: argv,
|
|
14
|
+
options: {
|
|
15
|
+
dir: { type: "string", short: "d" },
|
|
16
|
+
output: { type: "string", short: "o" },
|
|
17
|
+
json: { type: "boolean", default: false },
|
|
18
|
+
"no-introspect": { type: "boolean", default: false },
|
|
19
|
+
mcp: { type: "boolean", default: false },
|
|
20
|
+
"include-user": { type: "boolean", default: false },
|
|
21
|
+
timeout: { type: "string", default: "10000" },
|
|
22
|
+
help: { type: "boolean", short: "h", default: false }
|
|
23
|
+
},
|
|
24
|
+
strict: false,
|
|
25
|
+
allowPositionals: true
|
|
26
|
+
});
|
|
27
|
+
if (values.help) {
|
|
28
|
+
printHelp();
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
dir: values.dir ?? process.cwd(),
|
|
33
|
+
output: values.output ?? "ai-context-report.html",
|
|
34
|
+
json: values.json ?? false,
|
|
35
|
+
noIntrospect: values["no-introspect"] ?? false,
|
|
36
|
+
mcp: values.mcp ?? false,
|
|
37
|
+
includeUser: values["include-user"] ?? false,
|
|
38
|
+
timeout: parseInt(values.timeout ?? "10000", 10)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function printHelp() {
|
|
42
|
+
console.error(`
|
|
43
|
+
ai-context-inspector \u2014 Escanea el ecosistema AI de un proyecto
|
|
44
|
+
|
|
45
|
+
Uso:
|
|
46
|
+
npx @cocaxcode/ai-context-inspector [opciones]
|
|
47
|
+
|
|
48
|
+
Opciones:
|
|
49
|
+
-d, --dir <ruta> Directorio a escanear (default: cwd)
|
|
50
|
+
-o, --output <ruta> Archivo HTML de salida (default: ai-context-report.html)
|
|
51
|
+
--json Output JSON en stdout (no genera HTML)
|
|
52
|
+
--no-introspect No conectar a MCP servers
|
|
53
|
+
--include-user Incluir configuraci\xF3n del directorio de usuario
|
|
54
|
+
--timeout <ms> Timeout de introspecci\xF3n MCP (default: 10000)
|
|
55
|
+
--mcp Arrancar como MCP server
|
|
56
|
+
-h, --help Mostrar ayuda
|
|
57
|
+
`);
|
|
58
|
+
}
|
|
59
|
+
async function runCli(options) {
|
|
60
|
+
const dir = resolve(options.dir);
|
|
61
|
+
try {
|
|
62
|
+
await access(dir);
|
|
63
|
+
} catch {
|
|
64
|
+
console.error(`Error: El directorio no existe: ${dir}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
const config = {
|
|
68
|
+
dir,
|
|
69
|
+
includeUser: options.includeUser,
|
|
70
|
+
introspect: !options.noIntrospect,
|
|
71
|
+
timeout: options.timeout
|
|
72
|
+
};
|
|
73
|
+
console.error(`Escaneando ${dir}...`);
|
|
74
|
+
const result = await runAllScanners(config);
|
|
75
|
+
if (options.json) {
|
|
76
|
+
process.stdout.write(JSON.stringify(result, null, 2));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const html = generateHtml(result);
|
|
80
|
+
const outputPath = resolve(options.output);
|
|
81
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
82
|
+
await writeFile(outputPath, html, "utf-8");
|
|
83
|
+
console.error(`
|
|
84
|
+
Escaneo completado en ${result.scanDuration}ms
|
|
85
|
+
MCP Servers: ${result.mcpServers.length}
|
|
86
|
+
Tools: ${result.mcpServers.reduce((s, m) => s + (m.introspection?.tools.length ?? 0), 0)}
|
|
87
|
+
Archivos: ${result.contextFiles.length}
|
|
88
|
+
Skills: ${result.skills.length}
|
|
89
|
+
Memorias: ${result.memories.length}
|
|
90
|
+
Warnings: ${result.warnings.length}
|
|
91
|
+
|
|
92
|
+
Reporte: ${outputPath}`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/index.ts
|
|
96
|
+
async function main() {
|
|
97
|
+
const options = parseCliArgs(process.argv.slice(2));
|
|
98
|
+
if (options.mcp) {
|
|
99
|
+
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
100
|
+
const { createServer } = await import("./server-6EILEUO5.js");
|
|
101
|
+
const server = createServer();
|
|
102
|
+
const transport = new StdioServerTransport();
|
|
103
|
+
await server.connect(transport);
|
|
104
|
+
console.error("ai-context-inspector MCP server running on stdio");
|
|
105
|
+
} else {
|
|
106
|
+
await runCli(options);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
main().catch((error) => {
|
|
110
|
+
console.error("Fatal:", error);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
});
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
generateHtml,
|
|
4
|
+
introspectServers,
|
|
5
|
+
runAllScanners,
|
|
6
|
+
scanMcpConfigs
|
|
7
|
+
} from "./chunk-6HBCUZQJ.js";
|
|
8
|
+
|
|
9
|
+
// src/server.ts
|
|
10
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
|
+
|
|
12
|
+
// src/tools/scan.ts
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
function registerScanTool(server) {
|
|
15
|
+
server.tool(
|
|
16
|
+
"scan",
|
|
17
|
+
"Escanea un proyecto y descubre todo su ecosistema AI: MCP servers, archivos de contexto, skills y memorias",
|
|
18
|
+
{
|
|
19
|
+
dir: z.string().optional().describe("Directorio a escanear (default: cwd)"),
|
|
20
|
+
include_user: z.boolean().optional().describe("Incluir configuraci\xF3n del usuario"),
|
|
21
|
+
no_introspect: z.boolean().optional().describe("No conectar a MCP servers"),
|
|
22
|
+
timeout: z.number().optional().describe("Timeout de introspecci\xF3n en ms (default: 10000)")
|
|
23
|
+
},
|
|
24
|
+
async ({ dir, include_user, no_introspect, timeout }) => {
|
|
25
|
+
try {
|
|
26
|
+
const result = await runAllScanners({
|
|
27
|
+
dir: dir ?? process.cwd(),
|
|
28
|
+
includeUser: include_user ?? false,
|
|
29
|
+
introspect: !(no_introspect ?? false),
|
|
30
|
+
timeout: timeout ?? 1e4
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
type: "text",
|
|
36
|
+
text: JSON.stringify(result, null, 2)
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
} catch (err) {
|
|
41
|
+
return {
|
|
42
|
+
isError: true,
|
|
43
|
+
content: [
|
|
44
|
+
{
|
|
45
|
+
type: "text",
|
|
46
|
+
text: `Error escaneando: ${err.message}`
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/tools/introspect.ts
|
|
56
|
+
import { z as z2 } from "zod";
|
|
57
|
+
function registerIntrospectTool(server) {
|
|
58
|
+
server.tool(
|
|
59
|
+
"introspect_mcp",
|
|
60
|
+
"Introspecciona un MCP server espec\xEDfico: lista sus tools, resources y prompts",
|
|
61
|
+
{
|
|
62
|
+
server_name: z2.string().describe("Nombre del server MCP a introspeccionar"),
|
|
63
|
+
dir: z2.string().optional().describe("Directorio del proyecto (default: cwd)"),
|
|
64
|
+
timeout: z2.number().optional().describe("Timeout en ms (default: 10000)")
|
|
65
|
+
},
|
|
66
|
+
async ({ server_name, dir, timeout }) => {
|
|
67
|
+
try {
|
|
68
|
+
const { servers } = await scanMcpConfigs({
|
|
69
|
+
dir: dir ?? process.cwd(),
|
|
70
|
+
includeUser: true
|
|
71
|
+
});
|
|
72
|
+
const target = servers.find((s) => s.name === server_name);
|
|
73
|
+
if (!target) {
|
|
74
|
+
return {
|
|
75
|
+
isError: true,
|
|
76
|
+
content: [
|
|
77
|
+
{
|
|
78
|
+
type: "text",
|
|
79
|
+
text: `Server '${server_name}' no encontrado en la configuraci\xF3n. Servers disponibles: ${servers.map((s) => s.name).join(", ") || "(ninguno)"}`
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
await introspectServers([target], timeout ?? 1e4);
|
|
85
|
+
return {
|
|
86
|
+
content: [
|
|
87
|
+
{
|
|
88
|
+
type: "text",
|
|
89
|
+
text: JSON.stringify(target, null, 2)
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
};
|
|
93
|
+
} catch (err) {
|
|
94
|
+
return {
|
|
95
|
+
isError: true,
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Error introspectando: ${err.message}`
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/tools/report.ts
|
|
109
|
+
import { z as z3 } from "zod";
|
|
110
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
111
|
+
import { dirname, resolve } from "path";
|
|
112
|
+
function registerReportTool(server) {
|
|
113
|
+
server.tool(
|
|
114
|
+
"generate_report",
|
|
115
|
+
"Genera un dashboard HTML interactivo con el ecosistema AI del proyecto",
|
|
116
|
+
{
|
|
117
|
+
dir: z3.string().optional().describe("Directorio a escanear (default: cwd)"),
|
|
118
|
+
output: z3.string().optional().describe("Ruta del archivo HTML (default: ai-context-report.html)"),
|
|
119
|
+
no_introspect: z3.boolean().optional().describe("No conectar a MCP servers")
|
|
120
|
+
},
|
|
121
|
+
async ({ dir, output, no_introspect }) => {
|
|
122
|
+
try {
|
|
123
|
+
const result = await runAllScanners({
|
|
124
|
+
dir: dir ?? process.cwd(),
|
|
125
|
+
includeUser: false,
|
|
126
|
+
introspect: !(no_introspect ?? false),
|
|
127
|
+
timeout: 1e4
|
|
128
|
+
});
|
|
129
|
+
const html = generateHtml(result);
|
|
130
|
+
const outputPath = resolve(output ?? "ai-context-report.html");
|
|
131
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
132
|
+
await writeFile(outputPath, html, "utf-8");
|
|
133
|
+
return {
|
|
134
|
+
content: [
|
|
135
|
+
{
|
|
136
|
+
type: "text",
|
|
137
|
+
text: `Reporte generado: ${outputPath}
|
|
138
|
+
|
|
139
|
+
Resumen:
|
|
140
|
+
- MCP Servers: ${result.mcpServers.length}
|
|
141
|
+
- Tools: ${result.mcpServers.reduce((s, m) => s + (m.introspection?.tools.length ?? 0), 0)}
|
|
142
|
+
- Archivos: ${result.contextFiles.length}
|
|
143
|
+
- Skills: ${result.skills.length}
|
|
144
|
+
- Memorias: ${result.memories.length}`
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
};
|
|
148
|
+
} catch (err) {
|
|
149
|
+
return {
|
|
150
|
+
isError: true,
|
|
151
|
+
content: [
|
|
152
|
+
{
|
|
153
|
+
type: "text",
|
|
154
|
+
text: `Error generando reporte: ${err.message}`
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/server.ts
|
|
164
|
+
var VERSION = "0.1.0";
|
|
165
|
+
function createServer() {
|
|
166
|
+
const server = new McpServer({
|
|
167
|
+
name: "ai-context-inspector",
|
|
168
|
+
version: VERSION
|
|
169
|
+
});
|
|
170
|
+
registerScanTool(server);
|
|
171
|
+
registerIntrospectTool(server);
|
|
172
|
+
registerReportTool(server);
|
|
173
|
+
return server;
|
|
174
|
+
}
|
|
175
|
+
export {
|
|
176
|
+
createServer
|
|
177
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cocaxcode/ai-context-inspector",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scan any project to discover its complete AI ecosystem: MCP servers, tools, context files, skills, memories. Generates an interactive HTML dashboard. Works as CLI and MCP server.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ai-context-inspector": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"dev": "tsup --watch",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"test:watch": "vitest",
|
|
17
|
+
"test:coverage": "vitest run --coverage",
|
|
18
|
+
"lint": "eslint src/",
|
|
19
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
20
|
+
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"prepare": "npm run build",
|
|
23
|
+
"inspector": "npx @modelcontextprotocol/inspector node dist/index.js -- --mcp"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=20.0.0"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"mcp",
|
|
30
|
+
"mcp-server",
|
|
31
|
+
"model-context-protocol",
|
|
32
|
+
"ai-context",
|
|
33
|
+
"ai-inspector",
|
|
34
|
+
"ai-tools",
|
|
35
|
+
"mcp-introspection",
|
|
36
|
+
"claude",
|
|
37
|
+
"cursor",
|
|
38
|
+
"windsurf",
|
|
39
|
+
"copilot",
|
|
40
|
+
"gemini",
|
|
41
|
+
"codex",
|
|
42
|
+
"aider",
|
|
43
|
+
"cline",
|
|
44
|
+
"dashboard",
|
|
45
|
+
"html-report",
|
|
46
|
+
"context-files",
|
|
47
|
+
"skills",
|
|
48
|
+
"ai-ecosystem"
|
|
49
|
+
],
|
|
50
|
+
"author": "cocaxcode",
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"repository": {
|
|
53
|
+
"type": "git",
|
|
54
|
+
"url": "https://github.com/cocaxcode/ai-context-inspector.git"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/cocaxcode/ai-context-inspector#readme",
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "https://github.com/cocaxcode/ai-context-inspector/issues"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
62
|
+
"zod": "^3.25.0"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/node": "^22.15.0",
|
|
66
|
+
"@vitest/coverage-v8": "^3.2.0",
|
|
67
|
+
"eslint": "^9.28.0",
|
|
68
|
+
"prettier": "^3.5.0",
|
|
69
|
+
"tsup": "^8.5.0",
|
|
70
|
+
"typescript": "^5.8.0",
|
|
71
|
+
"typescript-eslint": "^8.33.0",
|
|
72
|
+
"vitest": "^3.2.0"
|
|
73
|
+
}
|
|
74
|
+
}
|