mcp-trust 0.1.0 → 0.2.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 +49 -1
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/install.d.ts +10 -0
- package/dist/commands/install.js +98 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/serve.d.ts +1 -0
- package/dist/commands/serve.js +195 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/index.js +59 -9
- package/dist/index.js.map +1 -1
- package/dist/install/packument.d.ts +23 -0
- package/dist/install/packument.js +48 -0
- package/dist/install/packument.js.map +1 -0
- package/dist/install/writer.d.ts +17 -0
- package/dist/install/writer.js +101 -0
- package/dist/install/writer.js.map +1 -0
- package/dist/prober/spawner.js +1 -1
- package/dist/reporters/terminal.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ npx mcp-doctor
|
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
mcp-doctor v0.
|
|
10
|
+
mcp-doctor v0.2.0
|
|
11
11
|
Auditing MCP servers installed on this machine
|
|
12
12
|
|
|
13
13
|
[ALIVE] B github [claude] 14 tools, 4 no-arg, 47ms
|
|
@@ -79,6 +79,54 @@ mcp-doctor audit --json # machine-readable output
|
|
|
79
79
|
mcp-doctor audit --config-only # list configured servers, don't probe
|
|
80
80
|
mcp-doctor audit --fail-on-dead # exit 1 if any server is dead (for CI)
|
|
81
81
|
mcp-doctor audit --concurrency 8 # parallelize probes
|
|
82
|
+
mcp-doctor install @scope/pkg # verify an npm package, then add it to your config
|
|
83
|
+
mcp-doctor serve # run as an MCP server exposing mcp_trust_audit
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### `install` — add a server safely
|
|
87
|
+
|
|
88
|
+
Resolves the package on npm, probes it live, then writes it to your config only if it passes. Refuses to add dead or F-graded servers unless you pass `--yes`. Defaults to Claude Desktop; pass `--client cursor` to target Cursor instead.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
mcp-trust install @modelcontextprotocol/server-github
|
|
92
|
+
mcp-trust install @modelcontextprotocol/server-github --client cursor
|
|
93
|
+
mcp-trust install @scope/pkg --yes # add even F-graded packages
|
|
94
|
+
mcp-trust install @scope/pkg --dry-run # probe + report, don't write
|
|
95
|
+
mcp-trust install @scope/pkg --name my-alias # override the entry name
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
If the requested name already exists in your config, the new entry is suffixed (`github-2`, `github-3`, …) instead of overwriting.
|
|
99
|
+
|
|
100
|
+
### `serve` — use mcp-trust from inside an agent
|
|
101
|
+
|
|
102
|
+
Runs mcp-trust as a Model Context Protocol server over stdio, exposing a single tool `mcp_trust_audit` that any MCP client (Claude Desktop, Cursor, Cline, your own agent) can call. The tool takes a list of server configurations, spawns each one, performs a real handshake, and returns a structured report.
|
|
103
|
+
|
|
104
|
+
```jsonc
|
|
105
|
+
// example call from any MCP client
|
|
106
|
+
{
|
|
107
|
+
"name": "mcp_trust_audit",
|
|
108
|
+
"arguments": {
|
|
109
|
+
"servers": {
|
|
110
|
+
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] },
|
|
111
|
+
"filesystem":{ "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] }
|
|
112
|
+
},
|
|
113
|
+
"noHealth": false,
|
|
114
|
+
"concurrency": 4
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Add it to your client config the same way you'd add any other MCP server:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"mcpServers": {
|
|
124
|
+
"mcp-trust": {
|
|
125
|
+
"command": "npx",
|
|
126
|
+
"args": ["-y", "mcp-trust", "serve"]
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
82
130
|
```
|
|
83
131
|
|
|
84
132
|
### Config locations scanned
|
package/dist/commands/index.d.ts
CHANGED
package/dist/commands/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type TargetClient } from "../install/writer.js";
|
|
2
|
+
export interface InstallOptions {
|
|
3
|
+
client?: TargetClient;
|
|
4
|
+
configPath?: string;
|
|
5
|
+
yes?: boolean;
|
|
6
|
+
name?: string;
|
|
7
|
+
noHealth?: boolean;
|
|
8
|
+
dryRun?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function runInstall(pkg: string, opts?: InstallOptions): Promise<void>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { fetchPackument } from "../install/packument.js";
|
|
3
|
+
import { probeServer } from "../prober/index.js";
|
|
4
|
+
import { checkRepoHealth, scoreServer } from "../checks/index.js";
|
|
5
|
+
import { resolveTarget, addServerToConfig, readExistingServers } from "../install/writer.js";
|
|
6
|
+
import { renderReport, summarize } from "../reporters/index.js";
|
|
7
|
+
function prompt(question) {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
process.stdout.write(question);
|
|
10
|
+
process.stdin.setEncoding("utf8");
|
|
11
|
+
process.stdin.once("data", (data) => {
|
|
12
|
+
const answer = data.toString().trim().toLowerCase();
|
|
13
|
+
resolve(answer === "" || answer === "y" || answer === "yes");
|
|
14
|
+
});
|
|
15
|
+
process.stdin.resume();
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function deriveNameFromPackage(pkg) {
|
|
19
|
+
return pkg.replace(/^@[\w.-]+\//, "").replace(/[^a-z0-9-]/gi, "-").toLowerCase();
|
|
20
|
+
}
|
|
21
|
+
export async function runInstall(pkg, opts = {}) {
|
|
22
|
+
if (!pkg || pkg.startsWith("-")) {
|
|
23
|
+
console.error(pc.red("error:") + " install requires a package name, e.g. `mcp-trust install @modelcontextprotocol/server-github`");
|
|
24
|
+
process.exit(2);
|
|
25
|
+
}
|
|
26
|
+
let resolved;
|
|
27
|
+
try {
|
|
28
|
+
console.log(pc.gray(`Resolving ${pkg} on npm…`));
|
|
29
|
+
resolved = await fetchPackument(pkg);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
console.error(pc.red("error:") + " " + (err instanceof Error ? err.message : String(err)));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
console.log(pc.bold(resolved.name) + pc.gray(` v${resolved.version}`));
|
|
36
|
+
if (resolved.description)
|
|
37
|
+
console.log(pc.gray(resolved.description));
|
|
38
|
+
if (resolved.repoUrl)
|
|
39
|
+
console.log(pc.gray(resolved.repoUrl));
|
|
40
|
+
console.log();
|
|
41
|
+
const desiredName = opts.name ?? deriveNameFromPackage(resolved.name);
|
|
42
|
+
const target = resolveTarget(opts.client, opts.configPath);
|
|
43
|
+
const existing = readExistingServers(target.path, target.client);
|
|
44
|
+
const collision = existing.find((s) => s.name === desiredName);
|
|
45
|
+
if (collision) {
|
|
46
|
+
console.log(pc.yellow(`A server named "${desiredName}" already exists in ${target.path}`));
|
|
47
|
+
}
|
|
48
|
+
const probeConfig = {
|
|
49
|
+
name: desiredName,
|
|
50
|
+
command: resolved.installCommand,
|
|
51
|
+
args: resolved.installArgs,
|
|
52
|
+
source: target.client,
|
|
53
|
+
configPath: target.path,
|
|
54
|
+
};
|
|
55
|
+
console.log(pc.bold("Probing server before adding…"));
|
|
56
|
+
const probed = await probeServer(probeConfig);
|
|
57
|
+
const token = opts.noHealth ? "" : process.env.GITHUB_TOKEN;
|
|
58
|
+
const health = opts.noHealth ? null : await checkRepoHealth(resolved.installCommand, resolved.installArgs, undefined, token);
|
|
59
|
+
const report = scoreServer(probed, health);
|
|
60
|
+
const reports = [report];
|
|
61
|
+
console.log();
|
|
62
|
+
const summary = summarize(reports);
|
|
63
|
+
renderReport(reports);
|
|
64
|
+
if (report.server.status !== "alive") {
|
|
65
|
+
console.log(pc.red(pc.bold("Server did not respond to the MCP handshake. Refusing to add a non-functional server.")));
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
if (report.verdict === "F" && !opts.yes) {
|
|
69
|
+
console.log(pc.yellow("Server scored F. Use --yes to install anyway."));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
if (opts.dryRun) {
|
|
73
|
+
console.log(pc.gray(`[dry-run] Would add "${desiredName}" to ${target.path}`));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (!opts.yes && process.stdin.isTTY) {
|
|
77
|
+
const ok = await prompt(`Add "${desiredName}" to ${target.path}? [Y/n] `);
|
|
78
|
+
if (!ok) {
|
|
79
|
+
console.log(pc.gray("Cancelled."));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const result = addServerToConfig(target.client, target.path, {
|
|
85
|
+
name: desiredName,
|
|
86
|
+
command: resolved.installCommand,
|
|
87
|
+
args: resolved.installArgs,
|
|
88
|
+
});
|
|
89
|
+
console.log();
|
|
90
|
+
console.log(pc.green(pc.bold("Installed.")) + ` Added "${result.finalName}" to ${result.path}`);
|
|
91
|
+
console.log(pc.gray("Run ") + pc.cyan("mcp-trust audit") + pc.gray(" to verify it's still healthy on next run."));
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
console.error(pc.red("error:") + " " + (err instanceof Error ? err.message : String(err)));
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runServe(): Promise<void>;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import * as readline from "node:readline";
|
|
2
|
+
import { probeServer } from "../prober/index.js";
|
|
3
|
+
import { checkRepoHealth, scoreServer } from "../checks/index.js";
|
|
4
|
+
const VERSION = "0.2.0";
|
|
5
|
+
const PROTOCOL_VERSION = "2024-11-05";
|
|
6
|
+
function send(id, payload) {
|
|
7
|
+
const msg = id !== undefined ? { jsonrpc: "2.0", id, ...payload } : { jsonrpc: "2.0", ...payload };
|
|
8
|
+
process.stdout.write(JSON.stringify(msg) + "\n");
|
|
9
|
+
}
|
|
10
|
+
function sendResponse(id, result) {
|
|
11
|
+
send(id, { result });
|
|
12
|
+
}
|
|
13
|
+
function sendError(id, code, message, data) {
|
|
14
|
+
send(id, { error: { code, message, data } });
|
|
15
|
+
}
|
|
16
|
+
function toolResult(text, isError = false) {
|
|
17
|
+
return { content: [{ type: "text", text }], isError };
|
|
18
|
+
}
|
|
19
|
+
function formatReportForAgent(reports) {
|
|
20
|
+
if (reports.length === 0) {
|
|
21
|
+
return "No servers were provided to audit.";
|
|
22
|
+
}
|
|
23
|
+
const lines = [];
|
|
24
|
+
lines.push(`mcp-trust audit: ${reports.length} server${reports.length === 1 ? "" : "s"} audited`);
|
|
25
|
+
lines.push("");
|
|
26
|
+
for (const r of reports) {
|
|
27
|
+
const icon = r.server.status === "alive" ? "ALIVE" : r.server.status.toUpperCase();
|
|
28
|
+
lines.push(`## ${r.server.config.name}`);
|
|
29
|
+
lines.push(` status: ${icon}`);
|
|
30
|
+
lines.push(` verdict: ${r.verdict} (score ${r.score})`);
|
|
31
|
+
lines.push(` source: ${r.server.config.source} (${r.server.config.command})`);
|
|
32
|
+
lines.push(` duration: ${r.server.durationMs}ms`);
|
|
33
|
+
if (r.server.toolCount > 0) {
|
|
34
|
+
lines.push(` tools: ${r.server.toolCount} (${r.server.emptyArgTools} require args)`);
|
|
35
|
+
}
|
|
36
|
+
if (r.server.errorMessage) {
|
|
37
|
+
lines.push(` error: ${r.server.errorMessage}`);
|
|
38
|
+
}
|
|
39
|
+
if (r.health) {
|
|
40
|
+
const age = r.health.lastCommitDaysAgo ?? "?";
|
|
41
|
+
lines.push(` repo: ${r.health.repo} | ${r.health.stars} stars | last commit ${age}d ago | ${r.health.weeklyDownloads} weekly downloads`);
|
|
42
|
+
if (r.health.archived)
|
|
43
|
+
lines.push(" archived: yes");
|
|
44
|
+
if (r.health.cveCount > 0)
|
|
45
|
+
lines.push(` cves: ${r.health.cveCount}`);
|
|
46
|
+
}
|
|
47
|
+
else if (r.server.status === "alive") {
|
|
48
|
+
lines.push(" repo: (health lookup skipped or unavailable)");
|
|
49
|
+
}
|
|
50
|
+
if (r.issues.length > 0) {
|
|
51
|
+
lines.push(" issues:");
|
|
52
|
+
for (const i of r.issues)
|
|
53
|
+
lines.push(` - ${i}`);
|
|
54
|
+
}
|
|
55
|
+
if (r.recommendations.length > 0) {
|
|
56
|
+
lines.push(" recommendations:");
|
|
57
|
+
for (const rec of r.recommendations)
|
|
58
|
+
lines.push(` - ${rec}`);
|
|
59
|
+
}
|
|
60
|
+
lines.push("");
|
|
61
|
+
}
|
|
62
|
+
const alive = reports.filter((r) => r.server.status === "alive").length;
|
|
63
|
+
const failing = reports.length - alive;
|
|
64
|
+
const avg = Math.round(reports.reduce((s, r) => s + r.score, 0) / reports.length);
|
|
65
|
+
lines.push(`summary: ${alive} alive, ${failing} failing, avg score ${avg}`);
|
|
66
|
+
return lines.join("\n");
|
|
67
|
+
}
|
|
68
|
+
function buildServers(input) {
|
|
69
|
+
const out = [];
|
|
70
|
+
for (const [name, def] of Object.entries(input.servers ?? {})) {
|
|
71
|
+
if (!def || typeof def !== "object" || typeof def.command !== "string")
|
|
72
|
+
continue;
|
|
73
|
+
out.push({
|
|
74
|
+
name,
|
|
75
|
+
command: def.command,
|
|
76
|
+
args: Array.isArray(def.args) ? def.args.map(String) : [],
|
|
77
|
+
env: def.env && typeof def.env === "object" ? Object.fromEntries(Object.entries(def.env).map(([k, v]) => [k, String(v)])) : undefined,
|
|
78
|
+
source: "manual",
|
|
79
|
+
configPath: "<mcp-tool-call>",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
async function runAuditTool(input) {
|
|
85
|
+
const servers = buildServers(input);
|
|
86
|
+
if (servers.length === 0)
|
|
87
|
+
return [];
|
|
88
|
+
const concurrency = Math.max(1, Math.min(input.concurrency ?? 4, 16));
|
|
89
|
+
const token = process.env.GITHUB_TOKEN;
|
|
90
|
+
const reports = [];
|
|
91
|
+
for (let i = 0; i < servers.length; i += concurrency) {
|
|
92
|
+
const batch = servers.slice(i, i + concurrency);
|
|
93
|
+
const results = await Promise.all(batch.map(async (cfg) => {
|
|
94
|
+
const probed = await probeServer(cfg);
|
|
95
|
+
const health = input.noHealth ? null : await checkRepoHealth(cfg.command, cfg.args, cfg.env, token);
|
|
96
|
+
return scoreServer(probed, health);
|
|
97
|
+
}));
|
|
98
|
+
reports.push(...results);
|
|
99
|
+
}
|
|
100
|
+
return reports;
|
|
101
|
+
}
|
|
102
|
+
const AUDIT_TOOL = {
|
|
103
|
+
name: "mcp_trust_audit",
|
|
104
|
+
description: "Audit a set of MCP server configurations. Spawns each server, performs a real MCP JSON-RPC initialize + tools/list handshake, then scores it A-F based on health, recency, tool surface, and known CVEs. Returns a structured report with issues and recommendations for each server.",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
servers: {
|
|
109
|
+
type: "object",
|
|
110
|
+
description: "Map of server name to { command, args?, env? }. Each will be spawned and probed.",
|
|
111
|
+
additionalProperties: {
|
|
112
|
+
type: "object",
|
|
113
|
+
properties: {
|
|
114
|
+
command: { type: "string", description: "Executable to run (e.g. 'npx', 'node', 'python')." },
|
|
115
|
+
args: { type: "array", items: { type: "string" }, description: "Arguments to pass." },
|
|
116
|
+
env: { type: "object", additionalProperties: { type: "string" }, description: "Environment variables." },
|
|
117
|
+
},
|
|
118
|
+
required: ["command"],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
noHealth: { type: "boolean", description: "Skip GitHub/npm repo health lookups (faster)." },
|
|
122
|
+
concurrency: { type: "number", description: "Max servers to probe in parallel (default 4, max 16)." },
|
|
123
|
+
},
|
|
124
|
+
required: ["servers"],
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
function handleInitialize(id) {
|
|
128
|
+
sendResponse(id, {
|
|
129
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
130
|
+
capabilities: { tools: {} },
|
|
131
|
+
serverInfo: { name: "mcp-trust", version: VERSION },
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function handleToolsList(id) {
|
|
135
|
+
sendResponse(id, { tools: [AUDIT_TOOL] });
|
|
136
|
+
}
|
|
137
|
+
async function handleToolsCall(id, params) {
|
|
138
|
+
if (!params || params.name !== "mcp_trust_audit") {
|
|
139
|
+
sendError(id, -32602, `Unknown tool: ${params?.name ?? "<none>"}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const args = (params.arguments ?? {});
|
|
143
|
+
if (!args.servers || typeof args.servers !== "object") {
|
|
144
|
+
sendResponse(id, toolResult("Error: 'servers' must be an object mapping name -> {command, args?, env?}", true));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const reports = await runAuditTool(args);
|
|
149
|
+
const text = formatReportForAgent(reports);
|
|
150
|
+
sendResponse(id, toolResult(text, false));
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
154
|
+
sendResponse(id, toolResult(`Audit failed: ${msg}`, true));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
export async function runServe() {
|
|
158
|
+
const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity, terminal: false });
|
|
159
|
+
rl.on("line", (line) => {
|
|
160
|
+
const trimmed = line.trim();
|
|
161
|
+
if (!trimmed)
|
|
162
|
+
return;
|
|
163
|
+
let msg;
|
|
164
|
+
try {
|
|
165
|
+
msg = JSON.parse(trimmed);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
sendError(undefined, -32700, "Parse error");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const { id, method, params } = msg;
|
|
172
|
+
if (method === "initialize") {
|
|
173
|
+
handleInitialize(id ?? 0);
|
|
174
|
+
}
|
|
175
|
+
else if (method === "tools/list") {
|
|
176
|
+
handleToolsList(id ?? 0);
|
|
177
|
+
}
|
|
178
|
+
else if (method === "tools/call") {
|
|
179
|
+
void handleToolsCall(id ?? 0, params);
|
|
180
|
+
}
|
|
181
|
+
else if (method && method.startsWith("notifications/")) {
|
|
182
|
+
// no response for notifications
|
|
183
|
+
}
|
|
184
|
+
else if (method === "ping") {
|
|
185
|
+
sendResponse(id ?? 0, {});
|
|
186
|
+
}
|
|
187
|
+
else if (id !== undefined) {
|
|
188
|
+
sendError(id, -32601, `Method not found: ${method}`);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
rl.on("close", () => {
|
|
192
|
+
process.exit(0);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import pc from "picocolors";
|
|
3
3
|
import { runAudit } from "./commands/index.js";
|
|
4
|
-
|
|
4
|
+
import { runInstall } from "./commands/install.js";
|
|
5
|
+
const HELP = `${pc.bold("mcp-trust")} ${pc.gray("v0.2.0")}
|
|
5
6
|
|
|
6
7
|
Audit the MCP servers installed on your machine. Detects dead, dangerous,
|
|
7
8
|
or fake servers before they hit production.
|
|
@@ -11,6 +12,8 @@ ${pc.bold("Usage:")}
|
|
|
11
12
|
|
|
12
13
|
${pc.bold("Commands:")}
|
|
13
14
|
audit Probe all configured MCP servers and report health (default)
|
|
15
|
+
install Verify an npm package is a healthy MCP server, then add it to your config
|
|
16
|
+
serve Run as an MCP server so other agents can call mcp_trust_audit
|
|
14
17
|
version Print version
|
|
15
18
|
help Show this message
|
|
16
19
|
|
|
@@ -25,12 +28,14 @@ ${pc.bold("Examples:")}
|
|
|
25
28
|
mcp-trust
|
|
26
29
|
mcp-trust audit --json
|
|
27
30
|
mcp-trust audit --fail-on-dead
|
|
28
|
-
mcp-trust
|
|
31
|
+
mcp-trust install @modelcontextprotocol/server-github
|
|
32
|
+
mcp-trust serve
|
|
29
33
|
`;
|
|
30
34
|
function parseArgs(argv) {
|
|
31
35
|
const args = argv.slice(2);
|
|
32
36
|
let command = "audit";
|
|
33
37
|
const options = {};
|
|
38
|
+
const positional = [];
|
|
34
39
|
for (let i = 0; i < args.length; i++) {
|
|
35
40
|
const arg = args[i];
|
|
36
41
|
if (arg === "help" || arg === "--help" || arg === "-h") {
|
|
@@ -39,8 +44,8 @@ function parseArgs(argv) {
|
|
|
39
44
|
else if (arg === "version" || arg === "--version" || arg === "-v") {
|
|
40
45
|
command = "version";
|
|
41
46
|
}
|
|
42
|
-
else if (arg === "audit") {
|
|
43
|
-
command =
|
|
47
|
+
else if (arg === "audit" || arg === "install" || arg === "serve") {
|
|
48
|
+
command = arg;
|
|
44
49
|
}
|
|
45
50
|
else if (arg === "--json") {
|
|
46
51
|
options.json = true;
|
|
@@ -52,7 +57,30 @@ function parseArgs(argv) {
|
|
|
52
57
|
options.failOnDead = true;
|
|
53
58
|
}
|
|
54
59
|
else if (arg === "--no-health") {
|
|
55
|
-
options.
|
|
60
|
+
options.noHealth = true;
|
|
61
|
+
options.githubToken = "";
|
|
62
|
+
}
|
|
63
|
+
else if (arg === "--yes" || arg === "-y") {
|
|
64
|
+
options.yes = true;
|
|
65
|
+
}
|
|
66
|
+
else if (arg === "--dry-run") {
|
|
67
|
+
options.dryRun = true;
|
|
68
|
+
}
|
|
69
|
+
else if (arg === "--client") {
|
|
70
|
+
const next = args[++i];
|
|
71
|
+
if (next === "claude" || next === "cursor" || next === "codex") {
|
|
72
|
+
options.client = next;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
console.error(pc.red("error:") + " --client must be one of: claude, cursor, codex");
|
|
76
|
+
process.exit(2);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (arg === "--config-path" || arg === "--config") {
|
|
80
|
+
options.configPath = args[++i];
|
|
81
|
+
}
|
|
82
|
+
else if (arg === "--name") {
|
|
83
|
+
options.name = args[++i];
|
|
56
84
|
}
|
|
57
85
|
else if (arg === "--concurrency") {
|
|
58
86
|
const next = args[++i];
|
|
@@ -63,28 +91,50 @@ function parseArgs(argv) {
|
|
|
63
91
|
}
|
|
64
92
|
options.concurrency = n;
|
|
65
93
|
}
|
|
66
|
-
else {
|
|
94
|
+
else if (arg?.startsWith("-")) {
|
|
67
95
|
console.error(pc.red("error:") + " unknown argument: " + arg);
|
|
68
96
|
console.error("Run " + pc.cyan("mcp-trust help") + " for usage");
|
|
69
97
|
process.exit(2);
|
|
70
98
|
}
|
|
99
|
+
else if (arg) {
|
|
100
|
+
positional.push(arg);
|
|
101
|
+
}
|
|
71
102
|
}
|
|
72
|
-
return { command, options };
|
|
103
|
+
return { command, options, positional };
|
|
73
104
|
}
|
|
74
105
|
async function main() {
|
|
75
|
-
const { command, options } = parseArgs(process.argv);
|
|
106
|
+
const { command, options, positional } = parseArgs(process.argv);
|
|
76
107
|
if (command === "help") {
|
|
77
108
|
console.log(HELP);
|
|
78
109
|
return;
|
|
79
110
|
}
|
|
80
111
|
if (command === "version") {
|
|
81
|
-
console.log("mcp-trust v0.
|
|
112
|
+
console.log("mcp-trust v0.2.0");
|
|
82
113
|
return;
|
|
83
114
|
}
|
|
84
115
|
if (command === "audit") {
|
|
85
116
|
await runAudit(options);
|
|
86
117
|
return;
|
|
87
118
|
}
|
|
119
|
+
if (command === "install") {
|
|
120
|
+
if (positional.length === 0) {
|
|
121
|
+
console.error(pc.red("error:") + " install requires a package name");
|
|
122
|
+
console.error(" e.g. mcp-trust install @modelcontextprotocol/server-github");
|
|
123
|
+
process.exit(2);
|
|
124
|
+
}
|
|
125
|
+
const pkg = positional[0];
|
|
126
|
+
if (!pkg) {
|
|
127
|
+
console.error(pc.red("error:") + " install requires a package name");
|
|
128
|
+
process.exit(2);
|
|
129
|
+
}
|
|
130
|
+
await runInstall(pkg, options);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (command === "serve") {
|
|
134
|
+
const { runServe } = await import("./commands/serve.js");
|
|
135
|
+
await runServe();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
88
138
|
}
|
|
89
139
|
main().catch((err) => {
|
|
90
140
|
console.error(pc.red("fatal:") + " " + (err instanceof Error ? err.message : String(err)));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAqB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface NpmPackument {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
bin?: Record<string, string> | string;
|
|
6
|
+
main?: string;
|
|
7
|
+
dependencies?: Record<string, string>;
|
|
8
|
+
repository?: {
|
|
9
|
+
url?: string;
|
|
10
|
+
} | string;
|
|
11
|
+
mcpName?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ResolvedPackage {
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
description: string;
|
|
17
|
+
installCommand: string;
|
|
18
|
+
installArgs: string[];
|
|
19
|
+
repoUrl: string | null;
|
|
20
|
+
}
|
|
21
|
+
export declare function fetchPackument(pkg: string): Promise<ResolvedPackage>;
|
|
22
|
+
export declare function resolveFromPackument(data: NpmPackument): ResolvedPackage;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const NPM_REGISTRY = "https://registry.npmjs.org";
|
|
2
|
+
export async function fetchPackument(pkg) {
|
|
3
|
+
const cleanName = pkg.replace(/^npm:/, "").trim();
|
|
4
|
+
const url = `${NPM_REGISTRY}/${encodeURIComponent(cleanName).replace(/^%40/, "@")}/latest`;
|
|
5
|
+
const res = await fetch(url, { headers: { Accept: "application/json" } });
|
|
6
|
+
if (!res.ok) {
|
|
7
|
+
if (res.status === 404) {
|
|
8
|
+
throw new Error(`Package "${cleanName}" not found on npm`);
|
|
9
|
+
}
|
|
10
|
+
throw new Error(`npm registry returned ${res.status} for ${cleanName}`);
|
|
11
|
+
}
|
|
12
|
+
const data = (await res.json());
|
|
13
|
+
return resolveFromPackument(data);
|
|
14
|
+
}
|
|
15
|
+
export function resolveFromPackument(data) {
|
|
16
|
+
const installCommand = "npx";
|
|
17
|
+
const installArgs = ["-y", data.name];
|
|
18
|
+
let repoUrl = null;
|
|
19
|
+
if (typeof data.repository === "string") {
|
|
20
|
+
repoUrl = data.repository;
|
|
21
|
+
}
|
|
22
|
+
else if (data.repository?.url) {
|
|
23
|
+
repoUrl = data.repository.url;
|
|
24
|
+
}
|
|
25
|
+
if (repoUrl) {
|
|
26
|
+
repoUrl = repoUrl
|
|
27
|
+
.replace(/^git\+/, "")
|
|
28
|
+
.replace(/\.git$/, "")
|
|
29
|
+
.replace(/^git:/, "https:")
|
|
30
|
+
.replace(/^ssh:\/\/git@/, "https://");
|
|
31
|
+
const match = repoUrl.match(/github\.com[/:]([\w.-]+)\/([\w.-]+)/);
|
|
32
|
+
if (match) {
|
|
33
|
+
repoUrl = `https://github.com/${match[1]}/${match[2]}`;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
repoUrl = null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
name: data.name,
|
|
41
|
+
version: data.version,
|
|
42
|
+
description: data.description ?? "",
|
|
43
|
+
installCommand,
|
|
44
|
+
installArgs,
|
|
45
|
+
repoUrl,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=packument.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packument.js","sourceRoot":"","sources":["../../src/install/packument.ts"],"names":[],"mappings":"AAWA,MAAM,YAAY,GAAG,4BAA4B,CAAC;AAWlD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAClD,MAAM,GAAG,GAAG,GAAG,YAAY,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC;IAC3F,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAC1E,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,YAAY,SAAS,oBAAoB,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC,MAAM,QAAQ,SAAS,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAiB,CAAC;IAChD,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAkB;IACrD,MAAM,cAAc,GAAG,KAAK,CAAC;IAC7B,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC;IAC5B,CAAC;SAAM,IAAI,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC;QAChC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;IAChC,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,GAAG,OAAO;aACd,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;aACrB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;aACrB,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC;aAC1B,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACnE,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,GAAG,sBAAsB,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;QACnC,cAAc;QACd,WAAW;QACX,OAAO;KACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ServerConfig } from "../types.js";
|
|
2
|
+
export type TargetClient = "claude" | "cursor" | "codex";
|
|
3
|
+
export declare function addServerToConfig(client: TargetClient, configPath: string, server: {
|
|
4
|
+
name: string;
|
|
5
|
+
command: string;
|
|
6
|
+
args: string[];
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
}): {
|
|
9
|
+
path: string;
|
|
10
|
+
finalName: string;
|
|
11
|
+
written: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function resolveTarget(client: TargetClient | undefined, explicitPath: string | undefined): {
|
|
14
|
+
client: TargetClient;
|
|
15
|
+
path: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function readExistingServers(configPath: string, client: TargetClient): ServerConfig[];
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, renameSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { homedir, platform } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
function defaultConfigPath(client) {
|
|
6
|
+
const home = homedir();
|
|
7
|
+
const win = platform() === "win32";
|
|
8
|
+
if (client === "claude") {
|
|
9
|
+
if (win) {
|
|
10
|
+
return join(process.env.APPDATA ?? join(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
|
|
11
|
+
}
|
|
12
|
+
if (platform() === "darwin") {
|
|
13
|
+
return join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
14
|
+
}
|
|
15
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(home, ".config"), "Claude", "claude_desktop_config.json");
|
|
16
|
+
}
|
|
17
|
+
if (client === "cursor") {
|
|
18
|
+
if (win)
|
|
19
|
+
return join(process.env.APPDATA ?? join(home, "AppData", "Roaming"), "Cursor", "mcp.json");
|
|
20
|
+
if (platform() === "darwin")
|
|
21
|
+
return join(home, "Library", "Application Support", "Cursor", "mcp.json");
|
|
22
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(home, ".config"), "Cursor", "mcp.json");
|
|
23
|
+
}
|
|
24
|
+
return join(home, ".codex", "config.toml");
|
|
25
|
+
}
|
|
26
|
+
export function addServerToConfig(client, configPath, server) {
|
|
27
|
+
if (client === "codex") {
|
|
28
|
+
throw new Error("Adding to Codex TOML config is not yet supported");
|
|
29
|
+
}
|
|
30
|
+
let parsed = {};
|
|
31
|
+
if (existsSync(configPath)) {
|
|
32
|
+
try {
|
|
33
|
+
const raw = readFileSync(configPath, "utf8");
|
|
34
|
+
parsed = JSON.parse(raw);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
throw new Error(`Failed to read existing config at ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const servers = parsed.mcpServers ?? {};
|
|
41
|
+
const finalName = ensureUniqueName(servers, server.name);
|
|
42
|
+
servers[finalName] = {
|
|
43
|
+
command: server.command,
|
|
44
|
+
args: server.args,
|
|
45
|
+
env: server.env,
|
|
46
|
+
};
|
|
47
|
+
parsed.mcpServers = servers;
|
|
48
|
+
const dir = dirname(configPath);
|
|
49
|
+
if (!existsSync(dir)) {
|
|
50
|
+
throw new Error(`Config directory does not exist: ${dir}`);
|
|
51
|
+
}
|
|
52
|
+
const tmpPath = `${configPath}.tmp-${process.pid}-${Date.now()}`;
|
|
53
|
+
try {
|
|
54
|
+
writeFileSync(tmpPath, JSON.stringify(parsed, null, 2) + "\n", "utf8");
|
|
55
|
+
renameSync(tmpPath, configPath);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
throw new Error(`Failed to write config at ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
59
|
+
}
|
|
60
|
+
return { path: configPath, finalName, written: true };
|
|
61
|
+
}
|
|
62
|
+
function ensureUniqueName(existing, desired) {
|
|
63
|
+
if (!(desired in existing))
|
|
64
|
+
return desired;
|
|
65
|
+
let i = 2;
|
|
66
|
+
while (`${desired}-${i}` in existing)
|
|
67
|
+
i++;
|
|
68
|
+
return `${desired}-${i}`;
|
|
69
|
+
}
|
|
70
|
+
export function resolveTarget(client, explicitPath) {
|
|
71
|
+
if (explicitPath) {
|
|
72
|
+
const resolvedClient = client ?? "claude";
|
|
73
|
+
return { client: resolvedClient, path: explicitPath };
|
|
74
|
+
}
|
|
75
|
+
if (!client)
|
|
76
|
+
return { client: "claude", path: defaultConfigPath("claude") };
|
|
77
|
+
return { client, path: defaultConfigPath(client) };
|
|
78
|
+
}
|
|
79
|
+
export function readExistingServers(configPath, client) {
|
|
80
|
+
if (!existsSync(configPath))
|
|
81
|
+
return [];
|
|
82
|
+
if (client === "codex")
|
|
83
|
+
return [];
|
|
84
|
+
try {
|
|
85
|
+
const raw = readFileSync(configPath, "utf8");
|
|
86
|
+
const parsed = JSON.parse(raw);
|
|
87
|
+
const servers = parsed.mcpServers ?? {};
|
|
88
|
+
return Object.entries(servers).map(([name, cfg]) => ({
|
|
89
|
+
name,
|
|
90
|
+
command: cfg.command,
|
|
91
|
+
args: cfg.args ?? [],
|
|
92
|
+
env: cfg.env,
|
|
93
|
+
source: client,
|
|
94
|
+
configPath,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/install/writer.ts"],"names":[],"mappings":"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"}
|
package/dist/prober/spawner.js
CHANGED
|
@@ -89,7 +89,7 @@ export async function probeServer(config) {
|
|
|
89
89
|
send(child, 1, "initialize", {
|
|
90
90
|
protocolVersion: PROTOCOL_VERSION,
|
|
91
91
|
capabilities: {},
|
|
92
|
-
clientInfo: { name: "mcp-doctor", version: "0.
|
|
92
|
+
clientInfo: { name: "mcp-doctor", version: "0.2.0" },
|
|
93
93
|
});
|
|
94
94
|
});
|
|
95
95
|
if (initResponse === "hang") {
|
|
@@ -25,7 +25,7 @@ function shortStatus(status) {
|
|
|
25
25
|
}
|
|
26
26
|
export function renderReport(reports) {
|
|
27
27
|
console.log();
|
|
28
|
-
console.log(pc.bold(pc.magenta("mcp-trust")) + pc.gray(" v0.
|
|
28
|
+
console.log(pc.bold(pc.magenta("mcp-trust")) + pc.gray(" v0.2.0"));
|
|
29
29
|
console.log(pc.gray("Auditing MCP servers installed on this machine"));
|
|
30
30
|
console.log();
|
|
31
31
|
if (reports.length === 0) {
|
package/package.json
CHANGED