mcp-lint 0.6.2 → 0.8.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 (53) hide show
  1. package/README.md +59 -3
  2. package/dist/cli/commands/check.js +160 -32
  3. package/dist/cli/commands/check.js.map +1 -1
  4. package/dist/cli/commands/init.js +1 -2
  5. package/dist/cli/commands/init.js.map +1 -1
  6. package/dist/cli/commands/snapshot.d.ts +2 -0
  7. package/dist/cli/commands/snapshot.js +56 -0
  8. package/dist/cli/commands/snapshot.js.map +1 -0
  9. package/dist/discover/files.d.ts +3 -0
  10. package/dist/discover/files.js +35 -0
  11. package/dist/discover/files.js.map +1 -0
  12. package/dist/discover/format.d.ts +6 -0
  13. package/dist/discover/format.js +20 -0
  14. package/dist/discover/format.js.map +1 -0
  15. package/dist/index.js +3 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/installed/config.d.ts +34 -0
  18. package/dist/installed/config.js +130 -0
  19. package/dist/installed/config.js.map +1 -0
  20. package/dist/installed/format.d.ts +2 -0
  21. package/dist/installed/format.js +72 -0
  22. package/dist/installed/format.js.map +1 -0
  23. package/dist/installed/lint.d.ts +19 -0
  24. package/dist/installed/lint.js +49 -0
  25. package/dist/installed/lint.js.map +1 -0
  26. package/dist/loaders/index.d.ts +1 -0
  27. package/dist/loaders/index.js +1 -0
  28. package/dist/loaders/index.js.map +1 -1
  29. package/dist/loaders/map-tools.d.ts +16 -0
  30. package/dist/loaders/map-tools.js +33 -0
  31. package/dist/loaders/map-tools.js.map +1 -0
  32. package/dist/loaders/remote-loader.d.ts +2 -0
  33. package/dist/loaders/remote-loader.js +37 -0
  34. package/dist/loaders/remote-loader.js.map +1 -0
  35. package/dist/loaders/sse-loader.d.ts +1 -1
  36. package/dist/loaders/sse-loader.js +3 -17
  37. package/dist/loaders/sse-loader.js.map +1 -1
  38. package/dist/loaders/stdio-loader.d.ts +8 -1
  39. package/dist/loaders/stdio-loader.js +58 -12
  40. package/dist/loaders/stdio-loader.js.map +1 -1
  41. package/dist/mcp-server.js +1 -1
  42. package/dist/recover/probe.js +1 -1
  43. package/dist/rules/index.js +2 -0
  44. package/dist/rules/index.js.map +1 -1
  45. package/dist/rules/tool-name.d.ts +2 -0
  46. package/dist/rules/tool-name.js +44 -0
  47. package/dist/rules/tool-name.js.map +1 -0
  48. package/dist/snapshot/serialize.d.ts +2 -0
  49. package/dist/snapshot/serialize.js +17 -0
  50. package/dist/snapshot/serialize.js.map +1 -0
  51. package/examples/github-action.yml +1 -1
  52. package/examples/names/unsafe.json +22 -0
  53. package/package.json +7 -3
package/README.md CHANGED
@@ -30,7 +30,10 @@ search-tool
30
30
  ## Installation
31
31
 
32
32
  ```bash
33
- # One-time use (no install)
33
+ # In a repo that already has tools.json
34
+ npx mcp-lint
35
+
36
+ # Or point at a file
34
37
  npx mcp-lint check tools.json
35
38
 
36
39
  # Global
@@ -45,6 +48,9 @@ npm install --save-dev mcp-lint
45
48
  ## Quick Start
46
49
 
47
50
  ```bash
51
+ # Look for tools.json, tools.yaml, or mcp-tools.json in this directory
52
+ npx mcp-lint
53
+
48
54
  # Check a JSON or YAML file
49
55
  mcp-lint check tools.json
50
56
 
@@ -65,6 +71,13 @@ mcp-lint-server
65
71
 
66
72
  # Score whether a tool failure tells the agent which tool to call next
67
73
  mcp-lint recover examples/recover/bad-credential.json
74
+
75
+ # Lint the stdio servers already configured for Cursor, Claude, and VS Code
76
+ mcp-lint check --installed
77
+
78
+ # Save a live tool list, then fail CI when a later snapshot gets worse
79
+ mcp-lint snapshot -o tools.json --server stdio -- node server.js
80
+ mcp-lint diff tools.json tools.next.json
68
81
  ```
69
82
 
70
83
  ---
@@ -187,6 +200,41 @@ mcp-lint diff tools-v1.json tools-v2.json --format json
187
200
 
188
201
  ---
189
202
 
203
+ ### `mcp-lint check --installed`
204
+
205
+ Reads the MCP configs already on this machine and lints each local stdio server. Nothing is uploaded. Remote URLs are skipped unless you pass `--remote`.
206
+
207
+ ```bash
208
+ mcp-lint check --installed
209
+ mcp-lint check --from .cursor/mcp.json
210
+ mcp-lint check --from .mcp.json --timeout 10000 --strict
211
+ ```
212
+
213
+ Looked-up files:
214
+
215
+ | Client | Path |
216
+ |--------|------|
217
+ | Cursor | `~/.cursor/mcp.json` and `./.cursor/mcp.json` |
218
+ | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) |
219
+ | Claude Code | `~/.claude.json`, `~/.claude/settings.json`, and `./.mcp.json` |
220
+ | VS Code | `~/Library/Application Support/Code/User/mcp.json` and `./.vscode/mcp.json` |
221
+
222
+ `--strict` also exits 1 when a configured server fails to start. Without it, a start failure is printed and the exit code follows the schema errors.
223
+
224
+ ---
225
+
226
+ ### `mcp-lint snapshot`
227
+
228
+ Writes the live `tools/list` as a stable JSON file. Commit that file and compare it with `diff` when the server changes. `diff` exits 1 when the new file introduces an error the old file did not have.
229
+
230
+ ```bash
231
+ mcp-lint snapshot -o tools.json --server stdio -- node server.js
232
+ mcp-lint snapshot -o tools.json --server http --url http://127.0.0.1:3000/mcp
233
+ mcp-lint diff tools.json tools.next.json
234
+ ```
235
+
236
+ ---
237
+
190
238
  ### `mcp-lint fix [input]`
191
239
 
192
240
  Auto-fixes issues that are safe to fix automatically (no semantic changes).
@@ -227,6 +275,14 @@ mcp-lint init --force # overwrite existing
227
275
  | `max-depth` | 🟡 warning | ❌ | Schema nesting deeper than 5 levels hurts LLM comprehension |
228
276
  | `no-unsupported-formats` | 🟡 warning | ✅ | Obscure `format` values (`iri`, `json-pointer`, `regex`…) not widely supported |
229
277
 
278
+ ### Tool names
279
+
280
+ | Rule | Severity | Fixable | Description |
281
+ |------|----------|---------|-------------|
282
+ | `tool-name/client-safe` | 🔴 error, 🟡 warning | ❌ | Names must match `^[A-Za-z0-9_-]{1,64}$`. A leading digit is a warning because Gemini rejects it. |
283
+
284
+ OpenAI and Azure use that pattern. A space, slash, or dot makes the tool disappear. See `examples/names/unsafe.json`.
285
+
230
286
  ### Claude-specific
231
287
 
232
288
  | Rule | Severity | Fixable | Description |
@@ -337,7 +393,7 @@ jobs:
337
393
  runs-on: ubuntu-latest
338
394
  steps:
339
395
  - uses: actions/checkout@v4
340
- - uses: robert19001-cmyk/mcp-lint@v0.6.2
396
+ - uses: robert19001-cmyk/mcp-lint@v0.8.0
341
397
  with:
342
398
  input: tools.json
343
399
  severity: warning
@@ -349,7 +405,7 @@ jobs:
349
405
 
350
406
  | Input | Default | Description |
351
407
  |-------|---------|-------------|
352
- | `input` | _(required)_ | Path to MCP tools JSON file |
408
+ | `input` | first `tools.json` in the repo | Path to an MCP tools JSON or YAML file |
353
409
  | `format` | `terminal` | `terminal\|json\|markdown` |
354
410
  | `severity` | `info` | Minimum severity to report |
355
411
  | `clients` | all | Comma-separated client filter |
@@ -1,7 +1,16 @@
1
1
  import { watch } from 'node:fs';
2
+ import { stat } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { resolve } from 'node:path';
5
+ import { discoverToolFiles, missingToolsMessage } from '../../discover/files.js';
6
+ import { formatDiscovered } from '../../discover/format.js';
2
7
  import { loadFile } from '../../loaders/file-loader.js';
3
8
  import { loadStdio } from '../../loaders/stdio-loader.js';
9
+ import { loadRemote } from '../../loaders/remote-loader.js';
4
10
  import { loadSSE } from '../../loaders/sse-loader.js';
11
+ import { collectInstalledServers } from '../../installed/config.js';
12
+ import { formatInstalled } from '../../installed/format.js';
13
+ import { lintInstalledServers } from '../../installed/lint.js';
5
14
  import { LintEngine } from '../../core/engine.js';
6
15
  import { allRules } from '../../rules/index.js';
7
16
  import { formatTerminal } from '../formatters/terminal.js';
@@ -18,7 +27,7 @@ function filterBySeverity(diagnostics, min) {
18
27
  }
19
28
  export function registerCheckCommand(program) {
20
29
  program
21
- .command('check [input]')
30
+ .command('check [input]', { isDefault: true })
22
31
  .description('Check MCP tool schemas for compatibility issues')
23
32
  .option('--format <format>', 'Output format: terminal|json|markdown', 'terminal')
24
33
  .option('--no-color', 'Disable terminal colors')
@@ -27,8 +36,13 @@ export function registerCheckCommand(program) {
27
36
  .option('--clients <clients>', 'Comma-separated client filter: claude,cursor,gemini,vscode')
28
37
  .option('--ignore <tools>', 'Comma-separated tool names to skip')
29
38
  .option('--quiet', 'Only output errors (no warnings/info)')
30
- .option('--server <type>', 'Server transport: stdio|sse')
31
- .option('--url <url>', 'SSE server URL (use with --server sse)')
39
+ .option('--server <type>', 'Server transport: stdio|sse|http')
40
+ .option('--url <url>', 'Remote server URL (use with --server sse|http)')
41
+ .option('--installed', 'Lint stdio servers declared in local Cursor, Claude, and VS Code configs')
42
+ .option('--from <path>', 'Lint servers declared in this MCP config. Repeatable.', collectPath, [])
43
+ .option('--remote', 'Also connect to URL servers. Off by default, so a scan stays on this machine.')
44
+ .option('--timeout <ms>', 'Per-server timeout in milliseconds for --installed, --from, and --server')
45
+ .option('--strict', 'With --installed or --from, exit 1 when a server fails to start')
32
46
  .option('--output-file <path>', 'Write results to a file instead of stdout')
33
47
  .option('--watch', 'Re-lint on file change (only works with file input)')
34
48
  .option('--score', 'Show quality score (0–100) per tool')
@@ -48,35 +62,94 @@ export function registerCheckCommand(program) {
48
62
  ...(options.ignore ? options.ignore.split(',').map((s) => s.trim()) : []),
49
63
  ],
50
64
  };
65
+ const from = options.from ?? [];
66
+ const scanning = Boolean(options.installed) || from.length > 0;
67
+ if (scanning && (input || options.server || options.watch)) {
68
+ throw new Error('Use --installed or --from on their own, without a tools file, --server, or --watch.');
69
+ }
70
+ const floor = severityFloor(options);
51
71
  let tools;
52
- if (options.server === 'stdio') {
53
- // Get everything after '--' in process.argv
72
+ let diagnostics;
73
+ let output;
74
+ if (scanning) {
75
+ const timeoutMs = parseTimeout(options.timeout, 20_000);
76
+ const collected = await collectInstalledServers({
77
+ scanInstalled: Boolean(options.installed),
78
+ from,
79
+ home: homedir(),
80
+ platform: process.platform,
81
+ cwd: process.cwd(),
82
+ });
83
+ if (collected.servers.length === 0 && collected.errors.length === 0) {
84
+ const where = options.installed
85
+ ? 'the Cursor, Claude, and VS Code configs on this machine'
86
+ : from.join(', ');
87
+ throw new Error(`No MCP servers found in ${where}.`);
88
+ }
89
+ const pluginRules = await loadPluginRules(fileConfig);
90
+ const engine = new LintEngine([...allRules, ...pluginRules], config);
91
+ const reports = await lintInstalledServers(collected.servers, {
92
+ remote: Boolean(options.remote),
93
+ timeoutMs,
94
+ lint: (found) => filterBySeverity(engine.lint(found), floor),
95
+ });
96
+ for (const problem of collected.errors) {
97
+ reports.unshift(configFailure(problem.path, problem.message));
98
+ }
99
+ tools = reports.flatMap((report) => report.tools);
100
+ diagnostics = reports.flatMap((report) => report.diagnostics);
101
+ output = formatInstalled(reports, options.format, !options.color);
102
+ const failedStart = reports.some((report) => report.status === 'failed');
103
+ await emit(output, options, tools, diagnostics);
104
+ return diagnostics.some((item) => item.severity === 'error') || (Boolean(options.strict) && failedStart);
105
+ }
106
+ else if (options.server === 'stdio') {
54
107
  const rawArgv = process.argv;
55
108
  const sepIdx = rawArgv.indexOf('--');
56
109
  if (sepIdx === -1 || sepIdx >= rawArgv.length - 1) {
57
110
  throw new Error('--server stdio requires a command after --, e.g.: mcp-lint check --server stdio -- node server.js');
58
111
  }
59
112
  const [cmd, ...cmdArgs] = rawArgv.slice(sepIdx + 1);
60
- tools = await loadStdio(cmd, cmdArgs);
113
+ tools = await loadStdio(cmd, cmdArgs, { timeoutMs: optionalTimeout(options.timeout) });
61
114
  }
62
115
  else if (options.server === 'sse') {
63
116
  if (!options.url)
64
117
  throw new Error('--server sse requires --url <url>');
65
- tools = await loadSSE(options.url);
118
+ tools = await loadSSE(options.url, optionalTimeout(options.timeout));
119
+ }
120
+ else if (options.server === 'http') {
121
+ if (!options.url)
122
+ throw new Error('--server http requires --url <url>');
123
+ tools = await loadRemote(options.url, 'http', optionalTimeout(options.timeout));
124
+ }
125
+ else if (await shouldDiscover(input)) {
126
+ const dir = input ? resolve(input) : process.cwd();
127
+ const files = await discoverToolFiles(dir);
128
+ if (files.length === 0)
129
+ throw new Error(missingToolsMessage(dir));
130
+ const pluginRules = await loadPluginRules(fileConfig);
131
+ const engine = new LintEngine([...allRules, ...pluginRules], config);
132
+ const groups = [];
133
+ const discoveredTools = [];
134
+ const discoveredDiagnostics = [];
135
+ for (const file of files) {
136
+ const found = await loadFile(file);
137
+ const foundDiagnostics = filterBySeverity(engine.lint(found), floor);
138
+ discoveredTools.push(...found);
139
+ discoveredDiagnostics.push(...foundDiagnostics);
140
+ groups.push({ file, diagnostics: foundDiagnostics });
141
+ }
142
+ await emit(formatDiscovered(groups, options.format, !options.color), options, discoveredTools, discoveredDiagnostics);
143
+ return discoveredDiagnostics.some((item) => item.severity === 'error');
66
144
  }
67
145
  else {
68
146
  if (!input)
69
- throw new Error('Specify an input file or use --server stdio|sse');
147
+ throw new Error('Specify an input file, --server stdio|sse|http, --installed, or --from <mcp.json>');
70
148
  tools = await loadFile(input);
71
149
  }
72
150
  const pluginRules = await loadPluginRules(fileConfig);
73
151
  const engine = new LintEngine([...allRules, ...pluginRules], config);
74
- let diagnostics = engine.lint(tools);
75
- const minSeverity = options.quiet
76
- ? 'error'
77
- : options.severity ?? 'info';
78
- diagnostics = filterBySeverity(diagnostics, minSeverity);
79
- let output;
152
+ diagnostics = filterBySeverity(engine.lint(tools), floor);
80
153
  if (options.format === 'json') {
81
154
  output = formatJson(diagnostics);
82
155
  }
@@ -86,23 +159,8 @@ export function registerCheckCommand(program) {
86
159
  else {
87
160
  output = formatTerminal(diagnostics, !options.color);
88
161
  }
89
- if (options.outputFile) {
90
- await writeFile(options.outputFile, output, 'utf8');
91
- }
92
- else {
93
- process.stdout.write(output);
94
- }
95
- if (options.score) {
96
- const report = computeQualityReport(tools, diagnostics);
97
- const gradeColor = (g) => g === 'A' ? chalk.green(g) : g === 'B' ? chalk.cyan(g) : g === 'C' ? chalk.yellow(g) : chalk.red(g);
98
- process.stdout.write(chalk.bold('\nQuality Score\n'));
99
- for (const t of report.tools) {
100
- process.stdout.write(` ${t.toolName.padEnd(30)} ${String(t.score).padStart(3)}/100 ${gradeColor(t.grade)} (${t.errors} errors, ${t.warnings} warnings)\n`);
101
- }
102
- process.stdout.write(`\n Overall: ${chalk.bold(String(report.overall))}/100 ${gradeColor(report.grade)}\n\n`);
103
- }
104
- const hasErrors = diagnostics.some((d) => d.severity === 'error');
105
- return hasErrors;
162
+ await emit(output, options, tools, diagnostics);
163
+ return diagnostics.some((item) => item.severity === 'error');
106
164
  }
107
165
  catch (err) {
108
166
  process.stderr.write(`Error: ${err.message}\n`);
@@ -110,7 +168,7 @@ export function registerCheckCommand(program) {
110
168
  }
111
169
  }
112
170
  if (options.watch) {
113
- if (!input || options.server) {
171
+ if (!input || options.server || options.installed || (options.from?.length ?? 0) > 0) {
114
172
  process.stderr.write('Error: --watch only works with file input\n');
115
173
  process.exit(2);
116
174
  }
@@ -132,4 +190,74 @@ export function registerCheckCommand(program) {
132
190
  }
133
191
  });
134
192
  }
193
+ async function shouldDiscover(input) {
194
+ if (!input)
195
+ return true;
196
+ try {
197
+ return (await stat(input)).isDirectory();
198
+ }
199
+ catch (err) {
200
+ if (err.code === 'ENOENT')
201
+ return false;
202
+ throw err;
203
+ }
204
+ }
205
+ function collectPath(value, previous) {
206
+ previous.push(value);
207
+ return previous;
208
+ }
209
+ function severityFloor(options) {
210
+ if (options.quiet)
211
+ return 'error';
212
+ if (options.severity === 'error' || options.severity === 'warning' || options.severity === 'info') {
213
+ return options.severity;
214
+ }
215
+ return 'info';
216
+ }
217
+ function parseTimeout(value, fallback) {
218
+ if (value === undefined)
219
+ return fallback;
220
+ const timeoutMs = Number(value);
221
+ if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
222
+ throw new Error('--timeout must be a positive number of milliseconds');
223
+ }
224
+ return timeoutMs;
225
+ }
226
+ function optionalTimeout(value) {
227
+ if (value === undefined)
228
+ return undefined;
229
+ return parseTimeout(value, 20_000);
230
+ }
231
+ function configFailure(path, message) {
232
+ return {
233
+ server: {
234
+ sourceLabel: 'config',
235
+ sourcePath: path,
236
+ name: '(config)',
237
+ kind: 'invalid',
238
+ args: [],
239
+ },
240
+ status: 'failed',
241
+ tools: [],
242
+ diagnostics: [],
243
+ error: message,
244
+ };
245
+ }
246
+ async function emit(output, options, tools, diagnostics) {
247
+ if (options.outputFile) {
248
+ await writeFile(options.outputFile, output, 'utf8');
249
+ }
250
+ else {
251
+ process.stdout.write(output);
252
+ }
253
+ if (!options.score)
254
+ return;
255
+ const report = computeQualityReport(tools, diagnostics);
256
+ const gradeColor = (grade) => grade === 'A' ? chalk.green(grade) : grade === 'B' ? chalk.cyan(grade) : grade === 'C' ? chalk.yellow(grade) : chalk.red(grade);
257
+ process.stdout.write(chalk.bold('\nQuality Score\n'));
258
+ for (const tool of report.tools) {
259
+ process.stdout.write(` ${tool.toolName.padEnd(30)} ${String(tool.score).padStart(3)}/100 ${gradeColor(tool.grade)} (${tool.errors} errors, ${tool.warnings} warnings)\n`);
260
+ }
261
+ process.stdout.write(`\n Overall: ${chalk.bold(String(report.overall))}/100 ${gradeColor(report.grade)}\n\n`);
262
+ }
135
263
  //# sourceMappingURL=check.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIhE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,cAAc,GAA6B,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAEnF,SAAS,gBAAgB,CAAC,WAAyB,EAAE,GAAa;IAChE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CAAC,iDAAiD,CAAC;SAC9D,MAAM,CAAC,mBAAmB,EAAE,uCAAuC,EAAE,UAAU,CAAC;SAChF,MAAM,CAAC,YAAY,EAAE,yBAAyB,CAAC;SAC/C,MAAM,CAAC,iBAAiB,EAAE,qCAAqC,CAAC;SAChE,MAAM,CAAC,oBAAoB,EAAE,gDAAgD,CAAC;SAC9E,MAAM,CAAC,qBAAqB,EAAE,4DAA4D,CAAC;SAC3F,MAAM,CAAC,kBAAkB,EAAE,oCAAoC,CAAC;SAChE,MAAM,CAAC,SAAS,EAAE,uCAAuC,CAAC;SAC1D,MAAM,CAAC,iBAAiB,EAAE,6BAA6B,CAAC;SACxD,MAAM,CAAC,aAAa,EAAE,wCAAwC,CAAC;SAC/D,MAAM,CAAC,sBAAsB,EAAE,2CAA2C,CAAC;SAC3E,MAAM,CAAC,SAAS,EAAE,qDAAqD,CAAC;SACxE,MAAM,CAAC,SAAS,EAAE,qCAAqC,CAAC;SACxD,oBAAoB,CAAC,IAAI,CAAC;SAC1B,MAAM,CAAC,KAAK,EACX,KAAyB,EACzB,OAaC,EACD,EAAE;QACF,KAAK,UAAU,OAAO;YACpB,IAAI,CAAC;gBACL,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAEpD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO;oBAChC,CAAC,CAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAgB;oBACjE,CAAC,CAAC,SAAS,CAAC;gBAEd,MAAM,MAAM,GAAW;oBACrB,GAAG,UAAU;oBACb,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC9C,MAAM,EAAE;wBACN,GAAG,CAAC,UAAU,CAAC,MAAM,IAAI,EAAE,CAAC;wBAC5B,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC1E;iBACF,CAAC;gBAEF,IAAI,KAAgB,CAAC;gBAErB,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;oBAC/B,4CAA4C;oBAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;oBAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBACrC,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAClD,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;oBACvH,CAAC;oBACD,MAAM,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;oBACpD,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACxC,CAAC;qBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;oBACpC,IAAI,CAAC,OAAO,CAAC,GAAG;wBAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;oBACvE,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACrC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,KAAK;wBAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;oBAC/E,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAChC,CAAC;gBAED,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;gBACtD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;gBACrE,IAAI,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAErC,MAAM,WAAW,GAAa,OAAO,CAAC,KAAK;oBACzC,CAAC,CAAC,OAAO;oBACT,CAAC,CAAE,OAAO,CAAC,QAAiC,IAAI,MAAM,CAAC;gBAEzD,WAAW,GAAG,gBAAgB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;gBAEzD,IAAI,MAAc,CAAC;gBACnB,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;oBAC9B,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;gBACnC,CAAC;qBAAM,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;oBACzC,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;gBACvC,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBACvD,CAAC;gBAED,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;oBACvB,MAAM,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBACtD,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC/B,CAAC;gBAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBAClB,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;oBACxD,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAC/B,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACtG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;oBACtD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;wBAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,YAAY,CAAC,CAAC,QAAQ,cAAc,CACxI,CAAC;oBACJ,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gBAAgB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAC1F,CAAC;gBACJ,CAAC;gBAEC,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;gBAClE,OAAO,SAAS,CAAC;YACnB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAW,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;gBAC3D,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;gBACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,KAAK,qBAAqB,CAAC,CAAC,CAAC;YACxE,MAAM,OAAO,EAAE,CAAC;YAEhB,IAAI,QAAQ,GAAyC,IAAI,CAAC;YAC1D,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE;gBAChB,IAAI,QAAQ;oBAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACrC,QAAQ,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;oBAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,kBAAkB,EAAE,oCAAoC,CAAC,CAAC,CAAC;oBAC3G,MAAM,OAAO,EAAE,CAAC;gBAClB,CAAC,EAAE,GAAG,CAAC,CAAC;YACV,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAG,MAAM,OAAO,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import { writeFile, access } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
  const DEFAULT_CONFIG = {
4
- $schema: 'https://raw.githubusercontent.com/robertmcp/mcp-lint/main/config-schema.json',
5
4
  rules: {
6
5
  'no-required-false': 'error',
7
6
  'no-content-encoding': 'error',
@@ -12,7 +11,7 @@ const DEFAULT_CONFIG = {
12
11
  'valid-json-schema-subset': 'error',
13
12
  'no-unsupported-formats': 'warning',
14
13
  },
15
- clients: ['claude', 'cursor', 'gemini', 'vscode'],
14
+ clients: ['claude', 'cursor', 'gemini', 'vscode', 'windsurf', 'cline', 'openai', 'continue'],
16
15
  ignore: [],
17
16
  maxDepth: 5,
18
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,cAAc,GAAG;IACrB,OAAO,EAAE,8EAA8E;IACvF,KAAK,EAAE;QACL,mBAAmB,EAAE,OAAO;QAC5B,qBAAqB,EAAE,OAAO;QAC9B,oBAAoB,EAAE,SAAS;QAC/B,eAAe,EAAE,OAAO;QACxB,WAAW,EAAE,SAAS;QACtB,mBAAmB,EAAE,OAAO;QAC5B,0BAA0B,EAAE,OAAO;QACnC,wBAAwB,EAAE,SAAS;KACpC;IACD,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;IACjD,MAAM,EAAE,EAAE;IACV,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,SAAS,EAAE,gCAAgC,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;QAE7D,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;gBACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6DAA6D,CAC9D,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YAAC,MAAM,CAAC;gBACP,8BAA8B;YAChC,CAAC;QACH,CAAC;QAED,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QACrF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,cAAc,GAAG;IACrB,KAAK,EAAE;QACL,mBAAmB,EAAE,OAAO;QAC5B,qBAAqB,EAAE,OAAO;QAC9B,oBAAoB,EAAE,SAAS;QAC/B,eAAe,EAAE,OAAO;QACxB,WAAW,EAAE,SAAS;QACtB,mBAAmB,EAAE,OAAO;QAC5B,0BAA0B,EAAE,OAAO;QACnC,wBAAwB,EAAE,SAAS;KACpC;IACD,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC;IAC5F,MAAM,EAAE,EAAE;IACV,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,SAAS,EAAE,gCAAgC,CAAC;SACnD,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;QAE7D,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;gBACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6DAA6D,CAC9D,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;YAAC,MAAM,CAAC;gBACP,8BAA8B;YAChC,CAAC;QACH,CAAC;QAED,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QACrF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerSnapshotCommand(program: Command): void;
@@ -0,0 +1,56 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { loadRemote } from '../../loaders/remote-loader.js';
3
+ import { loadStdio } from '../../loaders/stdio-loader.js';
4
+ import { serializeTools } from '../../snapshot/serialize.js';
5
+ export function registerSnapshotCommand(program) {
6
+ program
7
+ .command('snapshot')
8
+ .description('Write a stable tools JSON snapshot from a live MCP server')
9
+ .option('-o, --output <path>', 'Write the snapshot to this file instead of stdout')
10
+ .option('--server <type>', 'Server transport: stdio|sse|http')
11
+ .option('--url <url>', 'Remote server URL (use with --server sse|http)')
12
+ .option('--timeout <ms>', 'How long to wait for tools/list, in milliseconds', '20000')
13
+ .allowExcessArguments(true)
14
+ .action(async (options) => {
15
+ try {
16
+ const timeoutMs = parseTimeout(options.timeout);
17
+ const tools = await loadSnapshot(options.server, options.url, timeoutMs);
18
+ const body = serializeTools(tools);
19
+ if (options.output) {
20
+ await writeFile(options.output, body, 'utf8');
21
+ process.stderr.write(`Wrote ${tools.length} tool${tools.length === 1 ? '' : 's'} to ${options.output}\n`);
22
+ }
23
+ else {
24
+ process.stdout.write(body);
25
+ }
26
+ }
27
+ catch (err) {
28
+ process.stderr.write(`Error: ${err.message}\n`);
29
+ process.exit(2);
30
+ }
31
+ });
32
+ }
33
+ function parseTimeout(value) {
34
+ const timeoutMs = Number(value ?? '20000');
35
+ if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
36
+ throw new Error('--timeout must be a positive number of milliseconds');
37
+ }
38
+ return timeoutMs;
39
+ }
40
+ async function loadSnapshot(server, url, timeoutMs) {
41
+ if (server === 'stdio') {
42
+ const separator = process.argv.indexOf('--');
43
+ if (separator === -1 || separator >= process.argv.length - 1) {
44
+ throw new Error('snapshot --server stdio requires a command after --, e.g.: mcp-lint snapshot -o tools.json --server stdio -- node server.js');
45
+ }
46
+ const [command, ...args] = process.argv.slice(separator + 1);
47
+ return loadStdio(command, args, { timeoutMs });
48
+ }
49
+ if (server === 'sse' || server === 'http') {
50
+ if (!url)
51
+ throw new Error(`snapshot --server ${server} requires --url <url>`);
52
+ return loadRemote(url, server, timeoutMs);
53
+ }
54
+ throw new Error('snapshot requires --server stdio|sse|http');
55
+ }
56
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/cli/commands/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const TOOL_FILE_NAMES: readonly ["tools.json", "tools.yaml", "tools.yml", "mcp-tools.json", "mcp-tools.yaml", "mcp-tools.yml"];
2
+ export declare function discoverToolFiles(dir: string): Promise<string[]>;
3
+ export declare function missingToolsMessage(dir: string): string;
@@ -0,0 +1,35 @@
1
+ import { stat } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ export const TOOL_FILE_NAMES = [
4
+ 'tools.json',
5
+ 'tools.yaml',
6
+ 'tools.yml',
7
+ 'mcp-tools.json',
8
+ 'mcp-tools.yaml',
9
+ 'mcp-tools.yml',
10
+ ];
11
+ export async function discoverToolFiles(dir) {
12
+ const found = [];
13
+ for (const name of TOOL_FILE_NAMES) {
14
+ const path = join(dir, name);
15
+ try {
16
+ if ((await stat(path)).isFile())
17
+ found.push(path);
18
+ }
19
+ catch (err) {
20
+ if (err.code !== 'ENOENT')
21
+ throw err;
22
+ }
23
+ }
24
+ return found;
25
+ }
26
+ export function missingToolsMessage(dir) {
27
+ return [
28
+ `No tool schema in ${dir}.`,
29
+ `Looked for ${TOOL_FILE_NAMES.join(', ')}.`,
30
+ 'npx mcp-lint check tools.json',
31
+ 'npx mcp-lint check --from .cursor/mcp.json',
32
+ 'npx mcp-lint snapshot -o tools.json --server stdio -- node server.js',
33
+ ].join('\n');
34
+ }
35
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/discover/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,YAAY;IACZ,YAAY;IACZ,WAAW;IACX,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;CACP,CAAC;AAEX,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,GAAW;IACjD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,OAAO;QACL,qBAAqB,GAAG,GAAG;QAC3B,cAAc,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAC3C,+BAA+B;QAC/B,4CAA4C;QAC5C,sEAAsE;KACvE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Diagnostic } from '../core/diagnostic.js';
2
+ export interface DiscoveredFile {
3
+ file: string;
4
+ diagnostics: Diagnostic[];
5
+ }
6
+ export declare function formatDiscovered(groups: DiscoveredFile[], format: string, noColor?: boolean): string;
@@ -0,0 +1,20 @@
1
+ import chalk from 'chalk';
2
+ import { formatMarkdown } from '../cli/formatters/markdown.js';
3
+ import { formatTerminal } from '../cli/formatters/terminal.js';
4
+ export function formatDiscovered(groups, format, noColor = false) {
5
+ if (format === 'json') {
6
+ return `${JSON.stringify({
7
+ files: groups.map((group) => ({
8
+ file: group.file,
9
+ diagnostics: group.diagnostics.map(({ fix: _fix, ...diagnostic }) => diagnostic),
10
+ })),
11
+ }, null, 2)}\n`;
12
+ }
13
+ if (format === 'markdown') {
14
+ return `${groups.map((group) => `## ${group.file}\n\n${formatMarkdown(group.diagnostics).trimEnd()}`).join('\n\n')}\n`;
15
+ }
16
+ if (noColor)
17
+ chalk.level = 0;
18
+ return `${groups.map((group) => `${chalk.bold(group.file)}\n${formatTerminal(group.diagnostics, noColor)}`).join('\n')}`;
19
+ }
20
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/discover/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAO/D,MAAM,UAAU,gBAAgB,CAAC,MAAwB,EAAE,MAAc,EAAE,OAAO,GAAG,KAAK;IACxF,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;YACvB,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC;aACjF,CAAC,CAAC;SACJ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC1B,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IACzH,CAAC;IAED,IAAI,OAAO;QAAE,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAC7B,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,cAAc,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC3H,CAAC"}
package/dist/index.js CHANGED
@@ -8,11 +8,12 @@ import { registerExplainCommand } from './cli/commands/explain.js';
8
8
  import { registerDiffCommand } from './cli/commands/diff.js';
9
9
  import { registerPreflightCommand } from './cli/commands/preflight.js';
10
10
  import { registerRecoverCommand } from './cli/commands/recover.js';
11
+ import { registerSnapshotCommand } from './cli/commands/snapshot.js';
11
12
  const program = new Command();
12
13
  program
13
14
  .name('mcp-lint')
14
15
  .description('Lint MCP tool schemas and score whether an agent can recover from tool failures')
15
- .version('0.6.0');
16
+ .version('0.8.0');
16
17
  registerCheckCommand(program);
17
18
  registerFixCommand(program);
18
19
  registerInitCommand(program);
@@ -21,5 +22,6 @@ registerExplainCommand(program);
21
22
  registerDiffCommand(program);
22
23
  registerPreflightCommand(program);
23
24
  registerRecoverCommand(program);
25
+ registerSnapshotCommand(program);
24
26
  program.parse();
25
27
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,iFAAiF,CAAC;KAC9F,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAEhC,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,iFAAiF,CAAC;KAC9F,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAChC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAEjC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,34 @@
1
+ export interface ConfigOrigin {
2
+ label: string;
3
+ path: string;
4
+ }
5
+ export interface InstalledServer {
6
+ sourceLabel: string;
7
+ sourcePath: string;
8
+ name: string;
9
+ kind: 'stdio' | 'remote' | 'invalid';
10
+ command?: string;
11
+ args: string[];
12
+ env?: Record<string, string>;
13
+ cwd?: string;
14
+ url?: string;
15
+ remoteType?: string;
16
+ detail?: string;
17
+ }
18
+ export declare function candidateConfigFiles(home: string, platform: NodeJS.Platform, cwd: string): ConfigOrigin[];
19
+ export declare function parseInstalledConfig(raw: unknown, origin: ConfigOrigin): InstalledServer[];
20
+ export interface CollectResult {
21
+ servers: InstalledServer[];
22
+ errors: Array<{
23
+ path: string;
24
+ message: string;
25
+ }>;
26
+ lookedAt: string[];
27
+ }
28
+ export declare function collectInstalledServers(input: {
29
+ scanInstalled: boolean;
30
+ from: string[];
31
+ home: string;
32
+ platform: NodeJS.Platform;
33
+ cwd: string;
34
+ }): Promise<CollectResult>;