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.
- package/README.md +59 -3
- package/dist/cli/commands/check.js +160 -32
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/init.js +1 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/snapshot.d.ts +2 -0
- package/dist/cli/commands/snapshot.js +56 -0
- package/dist/cli/commands/snapshot.js.map +1 -0
- package/dist/discover/files.d.ts +3 -0
- package/dist/discover/files.js +35 -0
- package/dist/discover/files.js.map +1 -0
- package/dist/discover/format.d.ts +6 -0
- package/dist/discover/format.js +20 -0
- package/dist/discover/format.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/installed/config.d.ts +34 -0
- package/dist/installed/config.js +130 -0
- package/dist/installed/config.js.map +1 -0
- package/dist/installed/format.d.ts +2 -0
- package/dist/installed/format.js +72 -0
- package/dist/installed/format.js.map +1 -0
- package/dist/installed/lint.d.ts +19 -0
- package/dist/installed/lint.js +49 -0
- package/dist/installed/lint.js.map +1 -0
- package/dist/loaders/index.d.ts +1 -0
- package/dist/loaders/index.js +1 -0
- package/dist/loaders/index.js.map +1 -1
- package/dist/loaders/map-tools.d.ts +16 -0
- package/dist/loaders/map-tools.js +33 -0
- package/dist/loaders/map-tools.js.map +1 -0
- package/dist/loaders/remote-loader.d.ts +2 -0
- package/dist/loaders/remote-loader.js +37 -0
- package/dist/loaders/remote-loader.js.map +1 -0
- package/dist/loaders/sse-loader.d.ts +1 -1
- package/dist/loaders/sse-loader.js +3 -17
- package/dist/loaders/sse-loader.js.map +1 -1
- package/dist/loaders/stdio-loader.d.ts +8 -1
- package/dist/loaders/stdio-loader.js +58 -12
- package/dist/loaders/stdio-loader.js.map +1 -1
- package/dist/mcp-server.js +1 -1
- package/dist/recover/probe.js +1 -1
- package/dist/rules/index.js +2 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/tool-name.d.ts +2 -0
- package/dist/rules/tool-name.js +44 -0
- package/dist/rules/tool-name.js.map +1 -0
- package/dist/snapshot/serialize.d.ts +2 -0
- package/dist/snapshot/serialize.js +17 -0
- package/dist/snapshot/serialize.js.map +1 -0
- package/examples/github-action.yml +1 -1
- package/examples/names/unsafe.json +22 -0
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -30,7 +30,10 @@ search-tool
|
|
|
30
30
|
## Installation
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
#
|
|
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.
|
|
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` |
|
|
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>', '
|
|
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
|
-
|
|
53
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
90
|
-
|
|
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":"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"}
|
|
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,
|
|
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,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,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.
|
|
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;
|
|
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>;
|