@cybedefend/vibedefend 1.5.0 → 1.7.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 +71 -2
- package/dist/api/gateway-request.js +49 -0
- package/dist/api/gateway-request.js.map +1 -0
- package/dist/api/projects.js +67 -0
- package/dist/api/projects.js.map +1 -1
- package/dist/api/repository-link.js +157 -0
- package/dist/api/repository-link.js.map +1 -0
- package/dist/auth/auth-store.js +107 -25
- package/dist/auth/auth-store.js.map +1 -1
- package/dist/auth/auth.js +21 -0
- package/dist/auth/auth.js.map +1 -1
- package/dist/clients/cursor.js +5 -1
- package/dist/clients/cursor.js.map +1 -1
- package/dist/clients/vscode.js +38 -29
- package/dist/clients/vscode.js.map +1 -1
- package/dist/commands/mcp/allow.js +219 -0
- package/dist/commands/mcp/allow.js.map +1 -0
- package/dist/commands/mcp/connect.js +337 -0
- package/dist/commands/mcp/connect.js.map +1 -0
- package/dist/commands/mcp/index.js +170 -0
- package/dist/commands/mcp/index.js.map +1 -0
- package/dist/commands/mcp/proxy.js +320 -0
- package/dist/commands/mcp/proxy.js.map +1 -0
- package/dist/commands/mcp/scan.js +349 -0
- package/dist/commands/mcp/scan.js.map +1 -0
- package/dist/commands/mcp/sync.js +215 -0
- package/dist/commands/mcp/sync.js.map +1 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/diagnostics.js +78 -12
- package/dist/diagnostics.js.map +1 -1
- package/dist/doctor.js +19 -0
- package/dist/doctor.js.map +1 -1
- package/dist/guards-evaluator/analysis-types.js +27 -0
- package/dist/guards-evaluator/analysis-types.js.map +1 -0
- package/dist/guards-evaluator/command-analysis.js +572 -0
- package/dist/guards-evaluator/command-analysis.js.map +1 -0
- package/dist/guards-evaluator/command-view.js +586 -0
- package/dist/guards-evaluator/command-view.js.map +1 -0
- package/dist/guards-evaluator/env.js +11 -0
- package/dist/guards-evaluator/env.js.map +1 -0
- package/dist/guards-evaluator/evaluate.js +91 -41
- package/dist/guards-evaluator/evaluate.js.map +1 -1
- package/dist/guards-evaluator/index.js +2 -1
- package/dist/guards-evaluator/index.js.map +1 -1
- package/dist/guards-evaluator/inline-code.js +259 -0
- package/dist/guards-evaluator/inline-code.js.map +1 -0
- package/dist/guards-evaluator/normalize.js +716 -0
- package/dist/guards-evaluator/normalize.js.map +1 -0
- package/dist/guards-evaluator/preprocess.js +13 -5
- package/dist/guards-evaluator/preprocess.js.map +1 -1
- package/dist/guards-evaluator/redact.js +19 -0
- package/dist/guards-evaluator/redact.js.map +1 -1
- package/dist/guards-evaluator/regex.js +25 -3
- package/dist/guards-evaluator/regex.js.map +1 -1
- package/dist/guards-evaluator/safe-commands.js +155 -0
- package/dist/guards-evaluator/safe-commands.js.map +1 -0
- package/dist/guards-evaluator/triage.js +315 -0
- package/dist/guards-evaluator/triage.js.map +1 -0
- package/dist/hook-runner.js +24679 -5079
- package/dist/hooks/install.js +38 -0
- package/dist/hooks/install.js.map +1 -1
- package/dist/hooks/runtime/config.js +38 -0
- package/dist/hooks/runtime/config.js.map +1 -1
- package/dist/hooks/runtime/emit.js +94 -61
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/fetch-rules.js +22 -7
- package/dist/hooks/runtime/fetch-rules.js.map +1 -1
- package/dist/hooks/runtime/gateway-http-error.js +34 -0
- package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
- package/dist/hooks/runtime/guard-rules-cache.js +139 -17
- package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
- package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
- package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
- package/dist/hooks/runtime/judge-cache.js +6 -0
- package/dist/hooks/runtime/judge-cache.js.map +1 -1
- package/dist/hooks/runtime/judge-triage.js +193 -0
- package/dist/hooks/runtime/judge-triage.js.map +1 -0
- package/dist/hooks/runtime/judge.js +7 -1
- package/dist/hooks/runtime/judge.js.map +1 -1
- package/dist/hooks/runtime/pre-compact.js +12 -6
- package/dist/hooks/runtime/pre-compact.js.map +1 -1
- package/dist/hooks/runtime/resolve.js +90 -8
- package/dist/hooks/runtime/resolve.js.map +1 -1
- package/dist/hooks/runtime/retry-policy.js +57 -0
- package/dist/hooks/runtime/retry-policy.js.map +1 -0
- package/dist/hooks/runtime/review-sessions.js +74 -0
- package/dist/hooks/runtime/review-sessions.js.map +1 -0
- package/dist/hooks/runtime/script-resolve.js +695 -0
- package/dist/hooks/runtime/script-resolve.js.map +1 -0
- package/dist/hooks/runtime/session-activation.js +5 -1
- package/dist/hooks/runtime/session-activation.js.map +1 -1
- package/dist/hooks/runtime/session-review.js +163 -45
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +2 -1
- package/dist/hooks/runtime/session-start.js.map +1 -1
- package/dist/hooks/runtime/session-writes.js +232 -0
- package/dist/hooks/runtime/session-writes.js.map +1 -0
- package/dist/hooks/runtime/sniff.js +26 -7
- package/dist/hooks/runtime/sniff.js.map +1 -1
- package/dist/hooks/runtime/target-resolve.js +336 -0
- package/dist/hooks/runtime/target-resolve.js.map +1 -0
- package/dist/hooks/runtime/unmapped-tools.js +93 -0
- package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
- package/dist/hooks/runtime/usage-block.js +4 -0
- package/dist/hooks/runtime/usage-block.js.map +1 -1
- package/dist/hooks/runtime/user-prompt-submit.js +2 -1
- package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
- package/dist/hooks/runtime/wire-text.js +41 -0
- package/dist/hooks/runtime/wire-text.js.map +1 -0
- package/dist/hooks/runtime/work-dir.js +84 -0
- package/dist/hooks/runtime/work-dir.js.map +1 -0
- package/dist/index.js +45 -12
- package/dist/index.js.map +1 -1
- package/dist/install.js +174 -11
- package/dist/install.js.map +1 -1
- package/dist/link.js +74 -48
- package/dist/link.js.map +1 -1
- package/dist/login.js +77 -11
- package/dist/login.js.map +1 -1
- package/dist/mcp/auth/agent-sign-ins.js +174 -0
- package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
- package/dist/mcp/auth/callback.js +200 -0
- package/dist/mcp/auth/callback.js.map +1 -0
- package/dist/mcp/auth/connect.js +392 -0
- package/dist/mcp/auth/connect.js.map +1 -0
- package/dist/mcp/auth/discovery.js +399 -0
- package/dist/mcp/auth/discovery.js.map +1 -0
- package/dist/mcp/auth/oauth.js +326 -0
- package/dist/mcp/auth/oauth.js.map +1 -0
- package/dist/mcp/auth/probe.js +128 -0
- package/dist/mcp/auth/probe.js.map +1 -0
- package/dist/mcp/auth/secrets.js +446 -0
- package/dist/mcp/auth/secrets.js.map +1 -0
- package/dist/mcp/auth/store.js +260 -0
- package/dist/mcp/auth/store.js.map +1 -0
- package/dist/mcp/auth/tokenSource.js +55 -0
- package/dist/mcp/auth/tokenSource.js.map +1 -0
- package/dist/mcp/config/atomicWrite.js +98 -0
- package/dist/mcp/config/atomicWrite.js.map +1 -0
- package/dist/mcp/config/clients.js +171 -0
- package/dist/mcp/config/clients.js.map +1 -0
- package/dist/mcp/config/cybedefend-servers.js +48 -0
- package/dist/mcp/config/cybedefend-servers.js.map +1 -0
- package/dist/mcp/config/discover.js +114 -0
- package/dist/mcp/config/discover.js.map +1 -0
- package/dist/mcp/config/hook.js +123 -0
- package/dist/mcp/config/hook.js.map +1 -0
- package/dist/mcp/config/index.js +11 -0
- package/dist/mcp/config/index.js.map +1 -0
- package/dist/mcp/config/install.js +132 -0
- package/dist/mcp/config/install.js.map +1 -0
- package/dist/mcp/config/installed.js +37 -0
- package/dist/mcp/config/installed.js.map +1 -0
- package/dist/mcp/config/jsonEdit.js +119 -0
- package/dist/mcp/config/jsonEdit.js.map +1 -0
- package/dist/mcp/config/lock.js +102 -0
- package/dist/mcp/config/lock.js.map +1 -0
- package/dist/mcp/config/proxyBinary.js +211 -0
- package/dist/mcp/config/proxyBinary.js.map +1 -0
- package/dist/mcp/config/rewrite.js +388 -0
- package/dist/mcp/config/rewrite.js.map +1 -0
- package/dist/mcp/config/types.js +34 -0
- package/dist/mcp/config/types.js.map +1 -0
- package/dist/mcp/proxy/audit.js +83 -0
- package/dist/mcp/proxy/audit.js.map +1 -0
- package/dist/mcp/proxy/authInterceptor.js +119 -0
- package/dist/mcp/proxy/authInterceptor.js.map +1 -0
- package/dist/mcp/proxy/expand.js +93 -0
- package/dist/mcp/proxy/expand.js.map +1 -0
- package/dist/mcp/proxy/inject.js +412 -0
- package/dist/mcp/proxy/inject.js.map +1 -0
- package/dist/mcp/proxy/intercept.js +63 -0
- package/dist/mcp/proxy/intercept.js.map +1 -0
- package/dist/mcp/proxy/jsonrpc.js +153 -0
- package/dist/mcp/proxy/jsonrpc.js.map +1 -0
- package/dist/mcp/proxy/log.js +109 -0
- package/dist/mcp/proxy/log.js.map +1 -0
- package/dist/mcp/proxy/paths.js +57 -0
- package/dist/mcp/proxy/paths.js.map +1 -0
- package/dist/mcp/proxy/proxy.js +520 -0
- package/dist/mcp/proxy/proxy.js.map +1 -0
- package/dist/mcp/proxy/serverCheckTimer.js +75 -0
- package/dist/mcp/proxy/serverCheckTimer.js.map +1 -0
- package/dist/mcp/proxy/sessionLifecycle.js +29 -0
- package/dist/mcp/proxy/sessionLifecycle.js.map +1 -0
- package/dist/mcp/proxy/spec.js +203 -0
- package/dist/mcp/proxy/spec.js.map +1 -0
- package/dist/mcp/proxy/sse.js +77 -0
- package/dist/mcp/proxy/sse.js.map +1 -0
- package/dist/mcp/proxy/upstream.js +2 -0
- package/dist/mcp/proxy/upstream.js.map +1 -0
- package/dist/mcp/proxy/upstreamHttp.js +499 -0
- package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
- package/dist/mcp/proxy/upstreamStdio.js +188 -0
- package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
- package/dist/mcp/proxy/upstreams.js +143 -0
- package/dist/mcp/proxy/upstreams.js.map +1 -0
- package/dist/mcp/proxy/verifyInterceptor.js +718 -0
- package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
- package/dist/mcp/proxy/windowsCommand.js +99 -0
- package/dist/mcp/proxy/windowsCommand.js.map +1 -0
- package/dist/mcp/report/buffer.js +351 -0
- package/dist/mcp/report/buffer.js.map +1 -0
- package/dist/mcp/report/coalesce.js +165 -0
- package/dist/mcp/report/coalesce.js.map +1 -0
- package/dist/mcp/report/constants.js +51 -0
- package/dist/mcp/report/constants.js.map +1 -0
- package/dist/mcp/report/project.js +83 -0
- package/dist/mcp/report/project.js.map +1 -0
- package/dist/mcp/report/reporter.js +443 -0
- package/dist/mcp/report/reporter.js.map +1 -0
- package/dist/mcp/report/types.js +3 -0
- package/dist/mcp/report/types.js.map +1 -0
- package/dist/mcp/report/validate.js +179 -0
- package/dist/mcp/report/validate.js.map +1 -0
- package/dist/mcp/scan/args.js +228 -0
- package/dist/mcp/scan/args.js.map +1 -0
- package/dist/mcp/scan/results.js +253 -0
- package/dist/mcp/scan/results.js.map +1 -0
- package/dist/mcp/scan/types.js +40 -0
- package/dist/mcp/scan/types.js.map +1 -0
- package/dist/mcp/verify/api.js +514 -0
- package/dist/mcp/verify/api.js.map +1 -0
- package/dist/mcp/verify/backend.js +143 -0
- package/dist/mcp/verify/backend.js.map +1 -0
- package/dist/mcp/verify/cache.js +200 -0
- package/dist/mcp/verify/cache.js.map +1 -0
- package/dist/mcp/verify/contract-errors.js +198 -0
- package/dist/mcp/verify/contract-errors.js.map +1 -0
- package/dist/mcp/verify/digest.js +91 -0
- package/dist/mcp/verify/digest.js.map +1 -0
- package/dist/mcp/verify/factory.js +56 -0
- package/dist/mcp/verify/factory.js.map +1 -0
- package/dist/mcp/verify/identity.js +286 -0
- package/dist/mcp/verify/identity.js.map +1 -0
- package/dist/mcp/verify/policy-store.js +63 -0
- package/dist/mcp/verify/policy-store.js.map +1 -0
- package/dist/mcp/verify/policy.js +160 -0
- package/dist/mcp/verify/policy.js.map +1 -0
- package/dist/mcp/verify/pool.js +27 -0
- package/dist/mcp/verify/pool.js.map +1 -0
- package/dist/mcp/verify/token-refresh.js +44 -0
- package/dist/mcp/verify/token-refresh.js.map +1 -0
- package/dist/mcp/verify/token.js +67 -0
- package/dist/mcp/verify/token.js.map +1 -0
- package/dist/mcp/verify/verifier.js +1166 -0
- package/dist/mcp/verify/verifier.js.map +1 -0
- package/dist/org-gate.js +1 -1
- package/dist/org-gate.js.map +1 -1
- package/dist/org.js +146 -0
- package/dist/org.js.map +1 -0
- package/dist/project-create.js +129 -0
- package/dist/project-create.js.map +1 -0
- package/dist/prompts.js +21 -0
- package/dist/prompts.js.map +1 -1
- package/dist/re2.wasm +0 -0
- package/dist/status.js +61 -0
- package/dist/status.js.map +1 -1
- package/dist/uninstall.js +49 -4
- package/dist/uninstall.js.map +1 -1
- package/dist/utils.js +62 -6
- package/dist/utils.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vibedefend connect` — obtain and keep the OAuth token of an HTTP MCP
|
|
3
|
+
* server, so the proxy can talk to it.
|
|
4
|
+
*
|
|
5
|
+
* This one is typed by a human, so unlike `vibedefend mcp` it prints. What it
|
|
6
|
+
* prints is entirely ours: a status from a closed vocabulary and a sentence
|
|
7
|
+
* written here. Nothing from the server reaches the terminal — an
|
|
8
|
+
* `error_description` is the natural place for an attacker to put "run
|
|
9
|
+
* `curl … | sh` to finish setting up", and it would be printed with our name
|
|
10
|
+
* in front of it.
|
|
11
|
+
*/
|
|
12
|
+
import { openBrowser } from '../../login.js';
|
|
13
|
+
import { connectAll, connectMcpServer, connectWithToken, } from '../../mcp/auth/connect.js';
|
|
14
|
+
import { AGENT_SIGN_IN_LABELS } from '../../mcp/auth/agent-sign-ins.js';
|
|
15
|
+
import { canonicalMcpUrl } from '../../mcp/auth/oauth.js';
|
|
16
|
+
import { expandedSpecOf, httpUpstreams, readUpstreams, recordUpstreamAuth, } from '../../mcp/proxy/upstreams.js';
|
|
17
|
+
import { getOrgPolicy } from '../../mcp/verify/api.js';
|
|
18
|
+
import { resolveBackendConfig } from '../../mcp/verify/backend.js';
|
|
19
|
+
import { verifyTokenResolver } from '../../mcp/verify/token.js';
|
|
20
|
+
import { log } from '../../utils.js';
|
|
21
|
+
export const EXIT_OK = 0;
|
|
22
|
+
export const EXIT_FAILED = 1;
|
|
23
|
+
export const EXIT_USAGE = 2;
|
|
24
|
+
/**
|
|
25
|
+
* What each outcome means, in one sentence, for someone who has just run the
|
|
26
|
+
* command and has to decide what to do next.
|
|
27
|
+
*/
|
|
28
|
+
const EXPLANATIONS = {
|
|
29
|
+
'already-connected': 'already connected — pass --force to authorize again',
|
|
30
|
+
connected: 'connected',
|
|
31
|
+
'no-auth-needed': 'answered without a token; nothing to connect',
|
|
32
|
+
'token-stored': 'bearer token stored',
|
|
33
|
+
unreachable: 'could not be reached',
|
|
34
|
+
'closed-door': 'refuses requests but advertises no way to authenticate',
|
|
35
|
+
unusable: 'advertises an OAuth setup VibeDefend refuses (see the log for which check failed)',
|
|
36
|
+
'unverifiable-issuer': 'its authorization server does not implement RFC 9207, so the authorization response cannot be tied back to it, and strict issuer verification is on (--strict-issuer, or the organisation policy)',
|
|
37
|
+
'no-registration': 'has no dynamic client registration endpoint — register a client by hand and pass --client-id',
|
|
38
|
+
'registration-failed': 'refused the dynamic client registration',
|
|
39
|
+
'browser-failed': 'the local callback server could not be started',
|
|
40
|
+
denied: 'authorization was denied',
|
|
41
|
+
'state-mismatch': 'the authorization response carried an unknown or already-used state',
|
|
42
|
+
'issuer-mismatch': 'the authorization response came from a different issuer than the one discovered',
|
|
43
|
+
'missing-code': 'the authorization response carried no code',
|
|
44
|
+
'authorization-timeout': 'nothing came back from the browser in time',
|
|
45
|
+
'exchange-failed': 'the token exchange was refused',
|
|
46
|
+
'suspicious-redirect': 'answered a request carrying a secret with a redirect — treated as an exfiltration attempt, not a failure',
|
|
47
|
+
'store-failed': 'the token could not be stored anywhere',
|
|
48
|
+
'token-rejected': 'issued a token its own MCP endpoint then refused',
|
|
49
|
+
'sign-in-needed': 'needs a sign-in in the browser',
|
|
50
|
+
};
|
|
51
|
+
export async function runMcpConnectCommand(options, runtime, name) {
|
|
52
|
+
const stdout = runtime.stdout ?? process.stdout;
|
|
53
|
+
const stderr = runtime.stderr ?? process.stderr;
|
|
54
|
+
const targets = resolveTargets(name, options, runtime);
|
|
55
|
+
if ('error' in targets) {
|
|
56
|
+
stderr.write(`vibedefend connect: ${targets.error}\n`);
|
|
57
|
+
return EXIT_USAGE;
|
|
58
|
+
}
|
|
59
|
+
if (targets.list.length === 0) {
|
|
60
|
+
if (!options.json)
|
|
61
|
+
log.info('No HTTP MCP server to connect.');
|
|
62
|
+
return EXIT_OK;
|
|
63
|
+
}
|
|
64
|
+
const callbackPort = parseCallbackPort(options.callbackPort);
|
|
65
|
+
if (callbackPort === 'invalid') {
|
|
66
|
+
stderr.write(`vibedefend connect: --callback-port must be a TCP port between 1 and 65535 (got "${String(options.callbackPort)}")\n`);
|
|
67
|
+
return EXIT_USAGE;
|
|
68
|
+
}
|
|
69
|
+
if (options.token) {
|
|
70
|
+
if (targets.list.length !== 1) {
|
|
71
|
+
stderr.write('vibedefend connect: --token connects exactly one server\n');
|
|
72
|
+
return EXIT_USAGE;
|
|
73
|
+
}
|
|
74
|
+
const result = connectWithToken(targets.list[0].url, options.token, runtime.deps ?? {});
|
|
75
|
+
return report([{ ...result, name: targets.list[0].name }], options, runtime, stdout);
|
|
76
|
+
}
|
|
77
|
+
// A headless box, a container, an SSH session: there is no browser to open
|
|
78
|
+
// and the URL is the whole point. It goes to stderr so `--json` stays
|
|
79
|
+
// machine-readable on stdout.
|
|
80
|
+
const noBrowser = options.noBrowser || runtime.env.VIBEDEFEND_MCP_NO_BROWSER === '1';
|
|
81
|
+
const deps = {
|
|
82
|
+
openBrowser: noBrowser
|
|
83
|
+
? (url) => {
|
|
84
|
+
stderr.write(`Open this URL to authorize VibeDefend:\n${url}\n`);
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
: openBrowser,
|
|
88
|
+
clientId: options.clientId,
|
|
89
|
+
clientSecret: options.clientSecret,
|
|
90
|
+
scope: options.scope,
|
|
91
|
+
force: options.force,
|
|
92
|
+
reuse: options.reuse !== false,
|
|
93
|
+
clientInfo: { name: 'vibedefend', version: runtime.version },
|
|
94
|
+
strictIssuer: await strictIssuerPolicy(options, runtime.env, runtime.policyDeps),
|
|
95
|
+
callbackPort,
|
|
96
|
+
onEvent: options.json || options.quiet ? undefined : (event) => announce(event),
|
|
97
|
+
...runtime.deps,
|
|
98
|
+
};
|
|
99
|
+
const outcome = targets.list.length === 1
|
|
100
|
+
? {
|
|
101
|
+
results: [
|
|
102
|
+
{ ...(await connectMcpServer(targets.list[0].url, deps)), name: targets.list[0].name },
|
|
103
|
+
],
|
|
104
|
+
}
|
|
105
|
+
: await connectAll(targets.list, deps);
|
|
106
|
+
recordAuth(outcome.results, runtime.env);
|
|
107
|
+
return report(outcome.results, options, runtime, stdout);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The first pass of `vibedefend install` over the HTTP upstreams: take over
|
|
111
|
+
* the sign-ins Claude Code or Codex already hold, and nothing else. It asks
|
|
112
|
+
* nothing, registers no client and opens no browser, so the install only
|
|
113
|
+
* asks about the servers it leaves.
|
|
114
|
+
*
|
|
115
|
+
* A server wired in several clients is one server: counted once, under the
|
|
116
|
+
* first entry that names it.
|
|
117
|
+
*/
|
|
118
|
+
export async function takeOverAgentSignIns(runtime) {
|
|
119
|
+
const targets = resolveTargets(undefined, { all: true }, runtime);
|
|
120
|
+
if ('error' in targets || targets.list.length === 0)
|
|
121
|
+
return { reused: [], remaining: [] };
|
|
122
|
+
const deps = {
|
|
123
|
+
clientInfo: { name: 'vibedefend', version: runtime.version },
|
|
124
|
+
strictIssuer: await strictIssuerPolicy({}, runtime.env, runtime.policyDeps),
|
|
125
|
+
...runtime.deps,
|
|
126
|
+
force: false,
|
|
127
|
+
reuse: true,
|
|
128
|
+
reuseOnly: true,
|
|
129
|
+
onEvent: undefined,
|
|
130
|
+
};
|
|
131
|
+
const { results } = await connectAll(targets.list, deps);
|
|
132
|
+
recordAuth(results, runtime.env);
|
|
133
|
+
const seen = new Set();
|
|
134
|
+
const outcome = { reused: [], remaining: [] };
|
|
135
|
+
for (const result of results) {
|
|
136
|
+
if (seen.has(result.server))
|
|
137
|
+
continue;
|
|
138
|
+
seen.add(result.server);
|
|
139
|
+
const name = result.name ?? result.server;
|
|
140
|
+
if (result.status === 'reused' && result.from)
|
|
141
|
+
outcome.reused.push({ name, from: result.from });
|
|
142
|
+
else if (result.status === 'failed')
|
|
143
|
+
outcome.remaining.push(name);
|
|
144
|
+
}
|
|
145
|
+
return outcome;
|
|
146
|
+
}
|
|
147
|
+
/** Records in `upstreams.json` what each connect learned. */
|
|
148
|
+
function recordAuth(results, env) {
|
|
149
|
+
for (const result of results) {
|
|
150
|
+
if (!result.name)
|
|
151
|
+
continue;
|
|
152
|
+
const state = result.status === 'connected' ||
|
|
153
|
+
result.status === 'reused' ||
|
|
154
|
+
result.status === 'already-connected' ||
|
|
155
|
+
result.status === 'token-stored'
|
|
156
|
+
? 'connected'
|
|
157
|
+
: result.status === 'no-auth-needed'
|
|
158
|
+
? 'none'
|
|
159
|
+
: 'required';
|
|
160
|
+
try {
|
|
161
|
+
recordUpstreamAuth(result.name, state, env);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// The upstream file is a convenience here, not the credential store.
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Which servers to work on: a name from `upstreams.json`, an explicit URL, or
|
|
170
|
+
* every HTTP upstream.
|
|
171
|
+
*/
|
|
172
|
+
/**
|
|
173
|
+
* The url a connection is actually made to — expanded, exactly as the proxy
|
|
174
|
+
* expands it before contacting the server.
|
|
175
|
+
*
|
|
176
|
+
* The token store is keyed by url. Keyed on the stored
|
|
177
|
+
* `https://${TENANT}.example.com/mcp` form instead, the proxy would look up a
|
|
178
|
+
* key nobody ever wrote, and every tenant of one template would share a
|
|
179
|
+
* single token — one tenant's token presented to another.
|
|
180
|
+
*/
|
|
181
|
+
function connectUrlOf(entry, env) {
|
|
182
|
+
try {
|
|
183
|
+
const spec = expandedSpecOf(entry, env).value;
|
|
184
|
+
if (spec.transport === 'http')
|
|
185
|
+
return spec.url;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
/* an entry we cannot read stays exactly as it was stored */
|
|
189
|
+
}
|
|
190
|
+
return entry.url ?? '';
|
|
191
|
+
}
|
|
192
|
+
function resolveTargets(name, options, runtime) {
|
|
193
|
+
if (options.url) {
|
|
194
|
+
if (name || options.all)
|
|
195
|
+
return { error: '--url cannot be combined with a name or --all' };
|
|
196
|
+
if (!canonicalMcpUrl(options.url))
|
|
197
|
+
return { error: `not an http(s) url: ${options.url}` };
|
|
198
|
+
return { list: [{ name: options.url, url: options.url }] };
|
|
199
|
+
}
|
|
200
|
+
if (options.all) {
|
|
201
|
+
if (name)
|
|
202
|
+
return { error: '--all cannot be combined with a name' };
|
|
203
|
+
return {
|
|
204
|
+
list: httpUpstreams(runtime.env).map((entry) => ({
|
|
205
|
+
name: entry.name,
|
|
206
|
+
url: connectUrlOf(entry, runtime.env),
|
|
207
|
+
})),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
if (!name)
|
|
211
|
+
return { error: 'give a server name, --url <url>, or --all' };
|
|
212
|
+
const entry = readUpstreams(runtime.env).servers[name];
|
|
213
|
+
if (!entry) {
|
|
214
|
+
const known = Object.keys(readUpstreams(runtime.env).servers);
|
|
215
|
+
return {
|
|
216
|
+
error: known.length === 0
|
|
217
|
+
? `no upstream named "${name}": ~/.cybedefend/mcp/upstreams.json is empty. Run \`vibedefend install\` first, or pass --url.`
|
|
218
|
+
: `no upstream named "${name}". Known: ${known.join(', ')}.`,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
if (entry.transport !== 'http' || !entry.url) {
|
|
222
|
+
return { error: `"${name}" is a stdio server; there is nothing to connect.` };
|
|
223
|
+
}
|
|
224
|
+
return { list: [{ name, url: connectUrlOf(entry, runtime.env) }] };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Strict issuer verification, from either source that asks for it: the
|
|
228
|
+
* `--strict-issuer` flag, which only ever HARDENS, or the organisation's
|
|
229
|
+
* policy (`strictIssuer`), served by the backend. No environment variable:
|
|
230
|
+
* a security setting read from the environment of the machine it constrains
|
|
231
|
+
* is not a setting.
|
|
232
|
+
*
|
|
233
|
+
* Fail-open: no backend, no organization, or a policy that cannot be read
|
|
234
|
+
* means `false` — a cut network must neither open a door nor block the
|
|
235
|
+
* work, and the warning line still names the missing RFC 9207.
|
|
236
|
+
*/
|
|
237
|
+
export async function strictIssuerPolicy(options, env, deps = {}) {
|
|
238
|
+
if (options.strictIssuer)
|
|
239
|
+
return true;
|
|
240
|
+
try {
|
|
241
|
+
const backend = await (deps.resolveBackendConfigFn ?? resolveBackendConfig)({ env });
|
|
242
|
+
if (!backend)
|
|
243
|
+
return false;
|
|
244
|
+
const policy = await (deps.getOrgPolicyFn ?? getOrgPolicy)(backend, {
|
|
245
|
+
resolveTokenFn: verifyTokenResolver({ env }),
|
|
246
|
+
});
|
|
247
|
+
return policy.strictIssuer;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/** A port as typed on the command line: an integer in range, or nothing. */
|
|
254
|
+
export function parseCallbackPort(value) {
|
|
255
|
+
if (value === undefined)
|
|
256
|
+
return undefined;
|
|
257
|
+
if (!/^\d+$/.test(value.trim()))
|
|
258
|
+
return 'invalid';
|
|
259
|
+
const port = Number(value.trim());
|
|
260
|
+
return Number.isInteger(port) && port >= 1 && port <= 65535 ? port : 'invalid';
|
|
261
|
+
}
|
|
262
|
+
function announce(event) {
|
|
263
|
+
switch (event.kind) {
|
|
264
|
+
case 'probing':
|
|
265
|
+
log.step(`Checking whether ${event.server} needs a token`);
|
|
266
|
+
break;
|
|
267
|
+
case 'discovering':
|
|
268
|
+
log.info('It does. Looking up its authorization server…');
|
|
269
|
+
break;
|
|
270
|
+
case 'reusing':
|
|
271
|
+
log.info(`It does. Trying the sign-in ${AGENT_SIGN_IN_LABELS[event.from]} already holds…`);
|
|
272
|
+
break;
|
|
273
|
+
case 'registering':
|
|
274
|
+
log.info('Registering VibeDefend as an OAuth client…');
|
|
275
|
+
break;
|
|
276
|
+
case 'awaiting-browser':
|
|
277
|
+
log.info('Waiting for the browser. If it did not open, paste this URL:');
|
|
278
|
+
log.hint(event.url);
|
|
279
|
+
break;
|
|
280
|
+
case 'unverifiable-issuer':
|
|
281
|
+
log.warn(`${event.server}: the authorization response carried no issuer (RFC 9207), so it cannot be ` +
|
|
282
|
+
'tied back to its authorization server. Going on anyway; pass --strict-issuer, or have the ' +
|
|
283
|
+
'organisation policy require a strict issuer, to refuse such servers.');
|
|
284
|
+
break;
|
|
285
|
+
case 'exchanging':
|
|
286
|
+
log.info('Exchanging the authorization code…');
|
|
287
|
+
break;
|
|
288
|
+
case 'done':
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* One closing line, because twelve lines scrolling by are not a report.
|
|
294
|
+
*
|
|
295
|
+
* ⚠️ It names WHAT IS LEFT. That is the only actionable part of the batch: a
|
|
296
|
+
* summary that only counts the successes makes the user read the list again
|
|
297
|
+
* to find the two servers they still have to connect.
|
|
298
|
+
*/
|
|
299
|
+
export function summariseConnectResults(results) {
|
|
300
|
+
const connected = results.filter((result) => result.status === 'connected' || result.status === 'reused' || result.status === 'token-stored').length;
|
|
301
|
+
const already = results.filter((result) => result.status === 'already-connected' || result.status === 'no-auth-needed').length;
|
|
302
|
+
const outstanding = results.filter((result) => result.status === 'failed');
|
|
303
|
+
const counts = `${connected} connected, ${already} already in order, ${outstanding.length} failed`;
|
|
304
|
+
if (outstanding.length === 0)
|
|
305
|
+
return counts;
|
|
306
|
+
const names = outstanding.map((result) => result.name ?? result.server);
|
|
307
|
+
return (`${counts}\nStill to connect: ${names.join(', ')}\n` +
|
|
308
|
+
`Re-run \`vibedefend connect --all\` — what is already connected is skipped — ` +
|
|
309
|
+
`or one at a time: \`vibedefend connect ${names[0]}\``);
|
|
310
|
+
}
|
|
311
|
+
function report(results, options, runtime, stdout) {
|
|
312
|
+
if (options.json) {
|
|
313
|
+
stdout.write(`${JSON.stringify({ servers: results }, null, 2)}\n`);
|
|
314
|
+
}
|
|
315
|
+
else if (!options.quiet) {
|
|
316
|
+
for (const result of results) {
|
|
317
|
+
const label = result.name && result.name !== result.server ? `${result.name} (${result.server})` : result.server;
|
|
318
|
+
const explanation = result.status === 'reused' && result.from
|
|
319
|
+
? `connected with the sign-in ${AGENT_SIGN_IN_LABELS[result.from]} already holds`
|
|
320
|
+
: (EXPLANATIONS[result.reason ?? result.status] ?? result.status);
|
|
321
|
+
if (result.status === 'failed')
|
|
322
|
+
log.err(`${label}: ${explanation}`);
|
|
323
|
+
else if (result.status === 'connected' || result.status === 'reused' || result.status === 'token-stored') {
|
|
324
|
+
log.ok(`${label}: ${explanation}`);
|
|
325
|
+
}
|
|
326
|
+
else
|
|
327
|
+
log.info(`${label}: ${explanation}`);
|
|
328
|
+
}
|
|
329
|
+
// The closing report: more useful than the list as soon as it is longer
|
|
330
|
+
// than three lines, which it is as soon as a fleet of servers is wrapped.
|
|
331
|
+
if (results.length > 1)
|
|
332
|
+
log.step(summariseConnectResults(results));
|
|
333
|
+
}
|
|
334
|
+
void runtime;
|
|
335
|
+
return results.some((result) => result.status === 'failed') ? EXIT_FAILED : EXIT_OK;
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/commands/mcp/connect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { runMcpOverrideCommand } from './allow.js';
|
|
2
|
+
import { runMcpConnectCommand } from './connect.js';
|
|
3
|
+
import { runMcpProxyCommand } from './proxy.js';
|
|
4
|
+
import { runMcpScanCommand } from './scan.js';
|
|
5
|
+
import { runMcpSyncCommand } from './sync.js';
|
|
6
|
+
function collect(value, previous) {
|
|
7
|
+
return previous.concat([value]);
|
|
8
|
+
}
|
|
9
|
+
export function registerMcpCommand(program, version) {
|
|
10
|
+
const command = program
|
|
11
|
+
.command('mcp')
|
|
12
|
+
.description('Run the VibeDefend MCP proxy in front of an upstream MCP server. stdin/stdout carry JSON-RPC; this command is meant to be spawned by an agent, not typed by hand.')
|
|
13
|
+
.argument('[upstreamCommand...]', 'Upstream command and its arguments, after `--`. Example: vibedefend mcp -- npx -y @modelcontextprotocol/server-everything')
|
|
14
|
+
.option('--upstream <spec>', 'Upstream as an http(s) URL, or as a command line. Shell operators are refused; use `--` for anything the parser would not take.')
|
|
15
|
+
.option('--upstream-command <command>', 'Upstream executable (alternative to --upstream).')
|
|
16
|
+
.option('--upstream-arg <arg>', 'One argument for --upstream-command. Repeatable.', collect, [])
|
|
17
|
+
.option('--upstream-env <KEY=VALUE>', 'Extra environment for the upstream. Repeatable.', collect, [])
|
|
18
|
+
.option('--upstream-cwd <dir>', 'Working directory of the upstream.')
|
|
19
|
+
.option('--header <name:value>', 'Extra HTTP header for an http upstream. Repeatable.', collect, [])
|
|
20
|
+
.option('--name <id>', 'Upstream name from ~/.cybedefend/mcp/upstreams.json (Phase 5).')
|
|
21
|
+
.option('--log-level <level>', 'silent | error | warn | info | debug. Logs never touch stdout.')
|
|
22
|
+
.action(async (upstreamCommand, options) => {
|
|
23
|
+
const code = await runMcpProxyCommand({ ...options, trailing: upstreamCommand }, {
|
|
24
|
+
stdin: process.stdin,
|
|
25
|
+
stdout: process.stdout,
|
|
26
|
+
stderr: process.stderr,
|
|
27
|
+
env: process.env,
|
|
28
|
+
version,
|
|
29
|
+
});
|
|
30
|
+
process.exitCode = code;
|
|
31
|
+
});
|
|
32
|
+
registerConnectCommand(program, version);
|
|
33
|
+
registerSyncCommand(program);
|
|
34
|
+
registerUnwrapCommand(program);
|
|
35
|
+
registerScanCommand(program, version);
|
|
36
|
+
registerOverrideCommands(program);
|
|
37
|
+
// Help and parse errors must not land on the MCP channel.
|
|
38
|
+
command.configureOutput({
|
|
39
|
+
writeOut: (text) => process.stderr.write(text),
|
|
40
|
+
writeErr: (text) => process.stderr.write(text),
|
|
41
|
+
});
|
|
42
|
+
// Without this, commander throws on `--help` and the rejection surfaces as
|
|
43
|
+
// a crash; the exit code it computed is the right one to use.
|
|
44
|
+
command.exitOverride((error) => {
|
|
45
|
+
process.exit(error.exitCode);
|
|
46
|
+
});
|
|
47
|
+
return command;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* `vibedefend connect` — the OAuth side. A separate top-level command rather
|
|
51
|
+
* than `vibedefend mcp connect`, because `vibedefend mcp` is the proxy entry
|
|
52
|
+
* point an agent spawns and its stdout is a JSON-RPC channel; hanging a
|
|
53
|
+
* chatty interactive subcommand off it would be one typo away from writing a
|
|
54
|
+
* banner onto that channel.
|
|
55
|
+
*/
|
|
56
|
+
export function registerConnectCommand(program, version) {
|
|
57
|
+
return program
|
|
58
|
+
.command('connect')
|
|
59
|
+
.description('Authorize VibeDefend against an HTTP MCP server so the proxy can reach it. Takes over the sign-in Claude Code or Codex already holds for it, otherwise runs the OAuth flow in your browser.')
|
|
60
|
+
.argument('[name]', 'Server name from ~/.cybedefend/mcp/upstreams.json.')
|
|
61
|
+
.option('--all', 'Connect every HTTP upstream, skipping the ones already connected.')
|
|
62
|
+
.option('--url <url>', 'Connect a URL that is not in upstreams.json yet.')
|
|
63
|
+
.option('--token <bearer>', 'Store this bearer token instead of running the browser flow (CI).')
|
|
64
|
+
.option('--client-id <id>', 'Use a client registered out of band, for a server with no dynamic registration.')
|
|
65
|
+
.option('--client-secret <secret>', 'Secret of that client, when it has one.')
|
|
66
|
+
.option('--callback-port <port>', 'Listen on this loopback port for the authorization callback instead of an ephemeral one, for a client whose redirect URI was registered by hand. Remembered per server with --client-id.')
|
|
67
|
+
.option('--scope <scope>', 'Override the scopes advertised by the server.')
|
|
68
|
+
.option('--force', 'Authorize again even if a usable token is already stored.')
|
|
69
|
+
.option('--no-reuse', 'Do not take over the sign-in Claude Code or Codex already holds for the server: always run the browser flow.')
|
|
70
|
+
.option('--strict-issuer', 'Refuse an authorization server that does not implement RFC 9207 instead of warning. Also on when the organisation policy requires a strict issuer.')
|
|
71
|
+
.option('--no-browser', 'Print the authorization URL instead of launching a browser (headless, SSH, CI with a human).')
|
|
72
|
+
.option('--json', 'Machine-readable output.')
|
|
73
|
+
.option('--quiet', 'Print only the outcome.')
|
|
74
|
+
.action(async (name,
|
|
75
|
+
// Commander turns `--no-browser` into `browser: false` rather than
|
|
76
|
+
// `noBrowser: true`; the flag is negatable by construction.
|
|
77
|
+
options) => {
|
|
78
|
+
process.exitCode = await runMcpConnectCommand({ ...options, noBrowser: options.browser === false }, {
|
|
79
|
+
env: process.env,
|
|
80
|
+
version,
|
|
81
|
+
}, name);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* `vibedefend sync` — put the proxy in front of whatever is configured now.
|
|
86
|
+
*
|
|
87
|
+
* The same operation as the first install, on purpose: running it twice
|
|
88
|
+
* changes nothing, which is what lets the `SessionStart` hook and the proxy's
|
|
89
|
+
* own background refresh both call it.
|
|
90
|
+
*/
|
|
91
|
+
export function registerSyncCommand(program) {
|
|
92
|
+
return program
|
|
93
|
+
.command('sync')
|
|
94
|
+
.description('Put the VibeDefend proxy in front of the MCP servers configured in Claude Code, Cursor, VS Code, Windsurf and Claude Desktop. Idempotent.')
|
|
95
|
+
.option('--client <name>', 'Only this client: claude-code, claude-desktop, cursor, vscode, windsurf.')
|
|
96
|
+
.option('--dry-run', 'Show what would change and write nothing.')
|
|
97
|
+
.option('--quiet', 'Print only when something happened. Used by the SessionStart hook.')
|
|
98
|
+
.option('--json', 'Machine-readable output.')
|
|
99
|
+
.option('--no-backup', 'Do not keep a timestamped copy of each config file.')
|
|
100
|
+
.option('--hook <client>', 'Install the SessionStart hook for a client (claude-code) and exit.')
|
|
101
|
+
.option('--remove-hook', 'With --hook: remove it instead of installing it.')
|
|
102
|
+
.action(async (options) => {
|
|
103
|
+
process.exitCode = await runMcpSyncCommand({ ...options, noBackup: options.backup === false }, { env: process.env });
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* `vibedefend unwrap` — take the proxy back out. Not `uninstall`, which
|
|
108
|
+
* removes VibeDefend itself (and runs this first).
|
|
109
|
+
*
|
|
110
|
+
* It restores each original from `~/.cybedefend/mcp/upstreams.json`, not from
|
|
111
|
+
* the timestamped backup: the backup is for the user, and by the time anyone
|
|
112
|
+
* uninstalls it may have been edited, moved or cleaned up.
|
|
113
|
+
*/
|
|
114
|
+
export function registerUnwrapCommand(program) {
|
|
115
|
+
return program
|
|
116
|
+
.command('unwrap')
|
|
117
|
+
.description('Remove the VibeDefend proxy from the MCP servers it wraps, restoring each original entry.')
|
|
118
|
+
.option('--client <name>', 'Only this client.')
|
|
119
|
+
.option('--dry-run', 'Show what would change and write nothing.')
|
|
120
|
+
.option('--json', 'Machine-readable output.')
|
|
121
|
+
.option('--no-backup', 'Do not keep a timestamped copy of each config file.')
|
|
122
|
+
.action(async (options) => {
|
|
123
|
+
process.exitCode = await runMcpSyncCommand({ ...options, noBackup: options.backup === false }, { env: process.env }, 'uninstall');
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/** `vibedefend scan` — talk to every upstream once, with no agent in the loop. */
|
|
127
|
+
export function registerScanCommand(program, version) {
|
|
128
|
+
return program
|
|
129
|
+
.command('scan')
|
|
130
|
+
.description('Reach every registered MCP server once and report what it answers. No agent involved.')
|
|
131
|
+
.option('--name <id>', 'Scan one server instead of all of them.')
|
|
132
|
+
.option('--json', 'Machine-readable output.')
|
|
133
|
+
.action(async (options) => {
|
|
134
|
+
process.exitCode = await runMcpScanCommand(options, { env: process.env, version });
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* `vibedefend allow` and `vibedefend deny`.
|
|
139
|
+
*
|
|
140
|
+
* The decision the user makes after `vibedefend_alert` told the agent to ask
|
|
141
|
+
* them. It outranks the backend in both directions, which is why it lives
|
|
142
|
+
* with the verdicts it overrides rather than in a settings file of its own.
|
|
143
|
+
*
|
|
144
|
+
* The third command the plan names, `status`, is not registered here: the CLI
|
|
145
|
+
* already has one, about the install, and a second command with the same name
|
|
146
|
+
* would silently shadow it. The MCP verdicts are a section of that one
|
|
147
|
+
* instead, which is where somebody typing `vibedefend status` would look for
|
|
148
|
+
* them anyway.
|
|
149
|
+
*/
|
|
150
|
+
export function registerOverrideCommands(program) {
|
|
151
|
+
program
|
|
152
|
+
.command('allow')
|
|
153
|
+
.description('Use an MCP server even when VibeDefend flags it. The decision is yours and it outranks the verdict.')
|
|
154
|
+
.argument('<server>', 'Server name, as it appears in your client config.')
|
|
155
|
+
.option('--clear', "Undo it: VibeDefend's own verdict applies again.")
|
|
156
|
+
.option('--json', 'Machine-readable output.')
|
|
157
|
+
.action((server, options) => {
|
|
158
|
+
process.exitCode = runMcpOverrideCommand(server, 'allow', options, { env: process.env });
|
|
159
|
+
});
|
|
160
|
+
program
|
|
161
|
+
.command('deny')
|
|
162
|
+
.description('Refuse an MCP server whatever the verdict.')
|
|
163
|
+
.argument('<server>', 'Server name, as it appears in your client config.')
|
|
164
|
+
.option('--clear', "Undo it: VibeDefend's own verdict applies again.")
|
|
165
|
+
.option('--json', 'Machine-readable output.')
|
|
166
|
+
.action((server, options) => {
|
|
167
|
+
process.exitCode = runMcpOverrideCommand(server, 'deny', options, { env: process.env });
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/mcp/index.ts"],"names":[],"mappings":"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"}
|