@cybedefend/vibedefend 1.4.7 → 1.6.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 +77 -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 +264 -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 +24873 -5068
- 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 +126 -53
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/fetch-rules.js +27 -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 +21 -6
- package/dist/hooks/runtime/pre-compact.js.map +1 -1
- package/dist/hooks/runtime/resolve.js +108 -17
- 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 +226 -0
- package/dist/hooks/runtime/session-activation.js.map +1 -0
- package/dist/hooks/runtime/session-review.js +174 -46
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +35 -4
- 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 +8 -2
- 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 +99 -14
- 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 +397 -0
- package/dist/mcp/proxy/inject.js.map +1 -0
- package/dist/mcp/proxy/intercept.js +37 -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 +53 -0
- package/dist/mcp/proxy/paths.js.map +1 -0
- package/dist/mcp/proxy/proxy.js +510 -0
- package/dist/mcp/proxy/proxy.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 +559 -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/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 +475 -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 +182 -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 +173 -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 +158 -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 +1009 -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,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `vibedefend connect` flow, for one server.
|
|
3
|
+
*
|
|
4
|
+
* Probe → discovery → an agent's sign-in, else dynamic registration → browser
|
|
5
|
+
* → exchange → store. Each
|
|
6
|
+
* step is allowed to end the flow, and the outcome is a CLOSED vocabulary:
|
|
7
|
+
* nothing from the network is ever interpolated into a status, a reason or a
|
|
8
|
+
* hint. That is not squeamishness — a hostile server's `error_description` is
|
|
9
|
+
* the obvious place to put a sentence telling the user to run something, and
|
|
10
|
+
* we print these.
|
|
11
|
+
*
|
|
12
|
+
* Two properties this file exists to keep:
|
|
13
|
+
*
|
|
14
|
+
* - a token never leaves the machine. The only origins reached are the MCP
|
|
15
|
+
* server's and its authorization server's, both of which come from a
|
|
16
|
+
* discovery bound to the URL the user chose.
|
|
17
|
+
* - a failure on one server never stops the others. `connectAll` catches per
|
|
18
|
+
* server; the worst a bad entry can do is report itself.
|
|
19
|
+
*/
|
|
20
|
+
import { pkceChallenge, randomBase64url } from '../../auth/pkce.js';
|
|
21
|
+
import { findAgentSignIns } from './agent-sign-ins.js';
|
|
22
|
+
import { canonicalMcpUrl, exchangeMcpCode, McpSuspiciousRedirectError, refreshMcpToken, registerMcpClient, } from './oauth.js';
|
|
23
|
+
import { AuthorizationRedirectError, callbackRedirectUri, startMcpAuthorizationCallbackServer, } from './callback.js';
|
|
24
|
+
import { discoverMcpOAuthOutcome } from './discovery.js';
|
|
25
|
+
import { probeMcpHttp } from './probe.js';
|
|
26
|
+
import { loadMcpAuth, loadMcpClient, storeMcpAuth, storeMcpClient, validMcpAccessToken, } from './store.js';
|
|
27
|
+
const DEFAULT_AUTHORIZATION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
28
|
+
/**
|
|
29
|
+
* Stores a bearer supplied by the operator, for CI.
|
|
30
|
+
*
|
|
31
|
+
* There is no refresh token and no client: this credential dies when the
|
|
32
|
+
* server says so, which is exactly what a CI secret should do. No device flow
|
|
33
|
+
* in v1 — it needs a polling loop and a second UX, and a `--token` covers the
|
|
34
|
+
* case it was wanted for.
|
|
35
|
+
*/
|
|
36
|
+
export function connectWithToken(serverUrl, token, deps = {}) {
|
|
37
|
+
const server = canonicalMcpUrl(serverUrl) ?? serverUrl;
|
|
38
|
+
const stored = storeMcpAuth(serverUrl, {
|
|
39
|
+
accessToken: token,
|
|
40
|
+
refreshToken: null,
|
|
41
|
+
expiresAt: null,
|
|
42
|
+
clientId: 'headless',
|
|
43
|
+
clientSecret: null,
|
|
44
|
+
tokenEndpoint: '',
|
|
45
|
+
resource: server,
|
|
46
|
+
}, deps.storeDeps);
|
|
47
|
+
const result = stored
|
|
48
|
+
? { server, status: 'token-stored' }
|
|
49
|
+
: { server, status: 'failed', reason: 'store-failed' };
|
|
50
|
+
deps.onEvent?.({ kind: 'done', result });
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/** The whole flow for one server. Never throws. */
|
|
54
|
+
export async function connectMcpServer(serverUrl, deps = {}) {
|
|
55
|
+
const server = canonicalMcpUrl(serverUrl) ?? serverUrl;
|
|
56
|
+
const finish = (result) => {
|
|
57
|
+
deps.onEvent?.({ kind: 'done', result });
|
|
58
|
+
return result;
|
|
59
|
+
};
|
|
60
|
+
if (!deps.force && validMcpAccessToken(serverUrl, deps.storeDeps)) {
|
|
61
|
+
return finish({ server, status: 'already-connected' });
|
|
62
|
+
}
|
|
63
|
+
// 1. Does it even want a token?
|
|
64
|
+
deps.onEvent?.({ kind: 'probing', server });
|
|
65
|
+
const probe = await probeMcpHttp(serverUrl, {
|
|
66
|
+
fetchImpl: deps.fetchImpl,
|
|
67
|
+
timeoutMs: deps.timeoutMs,
|
|
68
|
+
clientInfo: deps.clientInfo,
|
|
69
|
+
// A stored-but-expired credential must not make an open server look
|
|
70
|
+
// closed, so the probe goes out bare.
|
|
71
|
+
token: null,
|
|
72
|
+
});
|
|
73
|
+
if (probe.verdict === 'open')
|
|
74
|
+
return finish({ server, status: 'no-auth-needed' });
|
|
75
|
+
if (probe.verdict === 'unreachable') {
|
|
76
|
+
return finish({ server, status: 'failed', reason: 'unreachable' });
|
|
77
|
+
}
|
|
78
|
+
if (probe.verdict === 'unusable') {
|
|
79
|
+
return finish({ server, status: 'failed', reason: 'unusable' });
|
|
80
|
+
}
|
|
81
|
+
// 2. Where do we authenticate?
|
|
82
|
+
deps.onEvent?.({ kind: 'discovering', server });
|
|
83
|
+
const discovery = await discoverMcpOAuthOutcome(serverUrl, {
|
|
84
|
+
fetchImpl: deps.fetchImpl,
|
|
85
|
+
timeoutMs: deps.timeoutMs,
|
|
86
|
+
knownChallenge: probe.challenge,
|
|
87
|
+
});
|
|
88
|
+
if (discovery.reason !== 'ok' || !discovery.endpoints) {
|
|
89
|
+
const reason = discovery.reason === 'no-oauth'
|
|
90
|
+
? 'closed-door'
|
|
91
|
+
: discovery.reason;
|
|
92
|
+
return finish({ server, status: 'failed', reason });
|
|
93
|
+
}
|
|
94
|
+
const endpoints = discovery.endpoints;
|
|
95
|
+
// 3. The RFC 9207 gate, before anything opens a browser: a refusal under
|
|
96
|
+
// strict verification. Otherwise the flow goes on, and whether the response
|
|
97
|
+
// can be tied back to its server is only known once it arrives (5b).
|
|
98
|
+
if (!endpoints.issParameterSupported && deps.strictIssuer) {
|
|
99
|
+
return finish({ server, status: 'failed', reason: 'unverifiable-issuer' });
|
|
100
|
+
}
|
|
101
|
+
// 3b. A sign-in an agent already holds for this very server.
|
|
102
|
+
if (deps.reuse !== false && !deps.force) {
|
|
103
|
+
const taken = await takeOverAgentSignIn(serverUrl, endpoints, deps);
|
|
104
|
+
if (taken.outcome === 'reused')
|
|
105
|
+
return finish({ server, status: 'reused', from: taken.from });
|
|
106
|
+
if (taken.outcome === 'failed')
|
|
107
|
+
return finish({ server, status: 'failed', reason: taken.reason });
|
|
108
|
+
}
|
|
109
|
+
if (deps.reuseOnly)
|
|
110
|
+
return finish({ server, status: 'failed', reason: 'sign-in-needed' });
|
|
111
|
+
// 4. A client to authorize as, and somewhere for the browser to land.
|
|
112
|
+
//
|
|
113
|
+
// The `state` is generated here and handed to the callback server, which
|
|
114
|
+
// is what checks it: `code` cannot reach the exchange before that check has
|
|
115
|
+
// passed, whatever this function does with it afterwards.
|
|
116
|
+
//
|
|
117
|
+
// A client registered by hand and remembered from a previous connect
|
|
118
|
+
// outlives the credential, and so does the port its redirect URI names.
|
|
119
|
+
const remembered = deps.clientId ? null : loadMcpClient(serverUrl, deps.storeDeps);
|
|
120
|
+
const callbackPort = deps.callbackPort ?? remembered?.callbackPort ?? undefined;
|
|
121
|
+
const state = randomBase64url(32);
|
|
122
|
+
const callback = await (deps.startCallbackServer ?? startMcpAuthorizationCallbackServer)(state, endpoints.issuer, endpoints.issParameterSupported, callbackPort === undefined ? {} : { port: callbackPort }).catch(() => null);
|
|
123
|
+
if (!callback)
|
|
124
|
+
return finish({ server, status: 'failed', reason: 'browser-failed' });
|
|
125
|
+
// Settled BEFORE the browser step, not after. The callback server rejects
|
|
126
|
+
// as soon as a bad response arrives — a replayed state, a foreign `iss` —
|
|
127
|
+
// and that can happen while `openBrowser` is still running. A rejection
|
|
128
|
+
// with nothing attached to it is an unhandled rejection, which crashes a
|
|
129
|
+
// process started with `--unhandled-rejections=strict`.
|
|
130
|
+
const settled = callback.redirectPromise.then((value) => ({ ok: true, value }), (error) => ({ ok: false, error }));
|
|
131
|
+
try {
|
|
132
|
+
const redirectUri = callbackRedirectUri(callback.port);
|
|
133
|
+
let clientId = deps.clientId ?? remembered?.clientId;
|
|
134
|
+
let clientSecret = deps.clientId
|
|
135
|
+
? (deps.clientSecret ?? null)
|
|
136
|
+
: (remembered?.clientSecret ?? null);
|
|
137
|
+
if (!clientId) {
|
|
138
|
+
if (!endpoints.registrationEndpoint) {
|
|
139
|
+
return finish({ server, status: 'failed', reason: 'no-registration' });
|
|
140
|
+
}
|
|
141
|
+
deps.onEvent?.({ kind: 'registering', server });
|
|
142
|
+
let registration;
|
|
143
|
+
try {
|
|
144
|
+
registration = await registerMcpClient(endpoints.registrationEndpoint, redirectUri, {
|
|
145
|
+
fetchImpl: deps.fetchImpl,
|
|
146
|
+
timeoutMs: deps.timeoutMs,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (error instanceof McpSuspiciousRedirectError) {
|
|
151
|
+
return finish({ server, status: 'failed', reason: 'suspicious-redirect' });
|
|
152
|
+
}
|
|
153
|
+
return finish({ server, status: 'failed', reason: 'registration-failed' });
|
|
154
|
+
}
|
|
155
|
+
if (!registration)
|
|
156
|
+
return finish({ server, status: 'failed', reason: 'registration-failed' });
|
|
157
|
+
clientId = registration.clientId;
|
|
158
|
+
clientSecret = registration.clientSecret;
|
|
159
|
+
}
|
|
160
|
+
// 5. The browser.
|
|
161
|
+
const verifier = randomBase64url(64);
|
|
162
|
+
const authorizationUrl = buildAuthorizationUrl({
|
|
163
|
+
endpoints,
|
|
164
|
+
clientId,
|
|
165
|
+
redirectUri,
|
|
166
|
+
state,
|
|
167
|
+
challenge: pkceChallenge(verifier),
|
|
168
|
+
scope: deps.scope ?? endpoints.scopesSupported.join(' '),
|
|
169
|
+
});
|
|
170
|
+
deps.onEvent?.({ kind: 'awaiting-browser', server, url: authorizationUrl });
|
|
171
|
+
// A browser that does not open is not fatal: the URL was just announced,
|
|
172
|
+
// and the user may paste it. Announcing it again only repeated it.
|
|
173
|
+
await (deps.openBrowser ?? (() => true))(authorizationUrl);
|
|
174
|
+
let outcome;
|
|
175
|
+
try {
|
|
176
|
+
outcome = await withTimeout(settled, deps.authorizationTimeoutMs ?? DEFAULT_AUTHORIZATION_TIMEOUT_MS);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return finish({ server, status: 'failed', reason: 'authorization-timeout' });
|
|
180
|
+
}
|
|
181
|
+
if (!outcome.ok) {
|
|
182
|
+
// `kind` is a closed vocabulary of ours, never a string from the wire.
|
|
183
|
+
if (outcome.error instanceof AuthorizationRedirectError) {
|
|
184
|
+
return finish({ server, status: 'failed', reason: outcome.error.kind });
|
|
185
|
+
}
|
|
186
|
+
return finish({ server, status: 'failed', reason: 'denied' });
|
|
187
|
+
}
|
|
188
|
+
const redirect = outcome.value;
|
|
189
|
+
// 5b. An AS that does not announce RFC 9207 may still stamp `iss`:
|
|
190
|
+
// mcp-service does on every response, and cannot announce it (Devin's
|
|
191
|
+
// client loses the parameter, then requires it). The callback server
|
|
192
|
+
// compared any `iss` it got, so only a response WITHOUT one could not be
|
|
193
|
+
// tied back to the server it came from.
|
|
194
|
+
if (!endpoints.issParameterSupported && redirect.iss === null) {
|
|
195
|
+
deps.onEvent?.({ kind: 'unverifiable-issuer', server });
|
|
196
|
+
}
|
|
197
|
+
// 6. The exchange.
|
|
198
|
+
deps.onEvent?.({ kind: 'exchanging', server });
|
|
199
|
+
let tokens;
|
|
200
|
+
try {
|
|
201
|
+
tokens = await exchangeMcpCode({
|
|
202
|
+
tokenEndpoint: endpoints.tokenEndpoint,
|
|
203
|
+
clientId,
|
|
204
|
+
clientSecret,
|
|
205
|
+
code: redirect.code,
|
|
206
|
+
codeVerifier: verifier,
|
|
207
|
+
redirectUri,
|
|
208
|
+
resource: endpoints.resource,
|
|
209
|
+
fetchImpl: deps.fetchImpl,
|
|
210
|
+
timeoutMs: deps.timeoutMs,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
if (error instanceof McpSuspiciousRedirectError) {
|
|
215
|
+
return finish({ server, status: 'failed', reason: 'suspicious-redirect' });
|
|
216
|
+
}
|
|
217
|
+
return finish({ server, status: 'failed', reason: 'exchange-failed' });
|
|
218
|
+
}
|
|
219
|
+
if (!tokens)
|
|
220
|
+
return finish({ server, status: 'failed', reason: 'exchange-failed' });
|
|
221
|
+
const persisted = storeMcpAuth(serverUrl, {
|
|
222
|
+
...tokens,
|
|
223
|
+
clientId,
|
|
224
|
+
clientSecret,
|
|
225
|
+
tokenEndpoint: endpoints.tokenEndpoint,
|
|
226
|
+
resource: endpoints.resource,
|
|
227
|
+
}, deps.storeDeps);
|
|
228
|
+
if (!persisted)
|
|
229
|
+
return finish({ server, status: 'failed', reason: 'store-failed' });
|
|
230
|
+
if (deps.clientId) {
|
|
231
|
+
// Registered by hand: remembered, so the next connect — after an
|
|
232
|
+
// invalid_grant erased the credential, say — needs no flags.
|
|
233
|
+
storeMcpClient(serverUrl, { clientId, clientSecret, callbackPort: deps.callbackPort ?? null }, deps.storeDeps);
|
|
234
|
+
}
|
|
235
|
+
// 7. Does the resource actually accept it? An AS can hand out a token the
|
|
236
|
+
// resource then refuses — measured on a server whose PRM advertised
|
|
237
|
+
// scopes we had not asked for.
|
|
238
|
+
const confirm = await probeMcpHttp(serverUrl, {
|
|
239
|
+
fetchImpl: deps.fetchImpl,
|
|
240
|
+
timeoutMs: deps.timeoutMs,
|
|
241
|
+
clientInfo: deps.clientInfo,
|
|
242
|
+
token: tokens.accessToken,
|
|
243
|
+
});
|
|
244
|
+
if (confirm.verdict === 'refused') {
|
|
245
|
+
return finish({ server, status: 'failed', reason: 'token-rejected' });
|
|
246
|
+
}
|
|
247
|
+
return finish({ server, status: 'connected' });
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
await callback.stop().catch(() => undefined);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Stores the first agent sign-in the server accepts.
|
|
255
|
+
*
|
|
256
|
+
* A token only goes back where it came from: the access token to the server
|
|
257
|
+
* it was issued for (the probe), the refresh token to the token endpoint
|
|
258
|
+
* discovered from that server, and only when the agent recorded no issuer or
|
|
259
|
+
* the same one. The agent's copy keeps working until the proxy renews it;
|
|
260
|
+
* after that, a server that rotates refresh tokens asks the agent to sign in
|
|
261
|
+
* again if it ever talks to the server without the proxy.
|
|
262
|
+
*/
|
|
263
|
+
async function takeOverAgentSignIn(serverUrl, endpoints, deps) {
|
|
264
|
+
let signIns;
|
|
265
|
+
try {
|
|
266
|
+
signIns = (deps.findAgentSignIns ?? ((url) => findAgentSignIns(url)))(serverUrl);
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
return { outcome: 'none' };
|
|
270
|
+
}
|
|
271
|
+
for (const signIn of signIns) {
|
|
272
|
+
if (signIn.issuer !== null && !sameIssuer(signIn.issuer, endpoints.issuer))
|
|
273
|
+
continue;
|
|
274
|
+
deps.onEvent?.({ kind: 'reusing', server: canonicalMcpUrl(serverUrl) ?? serverUrl, from: signIn.source });
|
|
275
|
+
let tokens = null;
|
|
276
|
+
const access = signIn.accessToken;
|
|
277
|
+
const fresh = access !== null && (signIn.expiresAt === null || signIn.expiresAt - 60_000 > Date.now());
|
|
278
|
+
if (fresh && (await accepted(serverUrl, access, deps))) {
|
|
279
|
+
tokens = { accessToken: access, refreshToken: signIn.refreshToken, expiresAt: signIn.expiresAt };
|
|
280
|
+
}
|
|
281
|
+
else if (signIn.refreshToken !== null) {
|
|
282
|
+
const renewed = await refreshMcpToken({
|
|
283
|
+
tokenEndpoint: endpoints.tokenEndpoint,
|
|
284
|
+
clientId: signIn.clientId,
|
|
285
|
+
clientSecret: signIn.clientSecret,
|
|
286
|
+
refreshToken: signIn.refreshToken,
|
|
287
|
+
resource: endpoints.resource,
|
|
288
|
+
fetchImpl: deps.fetchImpl,
|
|
289
|
+
timeoutMs: deps.timeoutMs,
|
|
290
|
+
});
|
|
291
|
+
if (!renewed.ok && renewed.reason === 'suspicious_redirect') {
|
|
292
|
+
return { outcome: 'failed', reason: 'suspicious-redirect' };
|
|
293
|
+
}
|
|
294
|
+
if (renewed.ok && (await accepted(serverUrl, renewed.tokens.accessToken, deps)))
|
|
295
|
+
tokens = renewed.tokens;
|
|
296
|
+
}
|
|
297
|
+
if (!tokens)
|
|
298
|
+
continue;
|
|
299
|
+
const stored = storeMcpAuth(serverUrl, {
|
|
300
|
+
...tokens,
|
|
301
|
+
clientId: signIn.clientId,
|
|
302
|
+
clientSecret: signIn.clientSecret,
|
|
303
|
+
tokenEndpoint: endpoints.tokenEndpoint,
|
|
304
|
+
resource: endpoints.resource,
|
|
305
|
+
}, deps.storeDeps);
|
|
306
|
+
return stored ? { outcome: 'reused', from: signIn.source } : { outcome: 'failed', reason: 'store-failed' };
|
|
307
|
+
}
|
|
308
|
+
return { outcome: 'none' };
|
|
309
|
+
}
|
|
310
|
+
async function accepted(serverUrl, token, deps) {
|
|
311
|
+
const probe = await probeMcpHttp(serverUrl, {
|
|
312
|
+
fetchImpl: deps.fetchImpl,
|
|
313
|
+
timeoutMs: deps.timeoutMs,
|
|
314
|
+
clientInfo: deps.clientInfo,
|
|
315
|
+
token,
|
|
316
|
+
});
|
|
317
|
+
return probe.verdict === 'open';
|
|
318
|
+
}
|
|
319
|
+
function sameIssuer(a, b) {
|
|
320
|
+
return a.trim().replace(/\/+$/, '') === b.trim().replace(/\/+$/, '');
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* The authorization URL, exactly as the browser will receive it.
|
|
324
|
+
*
|
|
325
|
+
* `resource` (RFC 8707) is always the canonical MCP URL, which is what stops
|
|
326
|
+
* the token from being valid elsewhere, and `scope` comes from the PRM: an AS
|
|
327
|
+
* asked for no scope issues a token the RESOURCE then refuses, which looks
|
|
328
|
+
* like a broken login after a successful OAuth.
|
|
329
|
+
*/
|
|
330
|
+
export function buildAuthorizationUrl(params) {
|
|
331
|
+
const url = new URL(params.endpoints.authorizationEndpoint);
|
|
332
|
+
url.searchParams.set('response_type', 'code');
|
|
333
|
+
url.searchParams.set('client_id', params.clientId);
|
|
334
|
+
url.searchParams.set('redirect_uri', params.redirectUri);
|
|
335
|
+
url.searchParams.set('code_challenge', params.challenge);
|
|
336
|
+
url.searchParams.set('code_challenge_method', 'S256');
|
|
337
|
+
url.searchParams.set('state', params.state);
|
|
338
|
+
url.searchParams.set('resource', params.endpoints.resource);
|
|
339
|
+
if (params.scope.trim() !== '')
|
|
340
|
+
url.searchParams.set('scope', params.scope.trim());
|
|
341
|
+
return url.toString();
|
|
342
|
+
}
|
|
343
|
+
class TimeoutError extends Error {
|
|
344
|
+
}
|
|
345
|
+
function withTimeout(promise, ms) {
|
|
346
|
+
return Promise.race([
|
|
347
|
+
promise,
|
|
348
|
+
new Promise((_, reject) => {
|
|
349
|
+
const timer = setTimeout(() => reject(new TimeoutError('authorization timed out')), ms);
|
|
350
|
+
if (typeof timer.unref === 'function')
|
|
351
|
+
timer.unref();
|
|
352
|
+
}),
|
|
353
|
+
]);
|
|
354
|
+
}
|
|
355
|
+
/** Whether a usable credential is on file for this server. */
|
|
356
|
+
export function isConnected(serverUrl, deps = {}) {
|
|
357
|
+
return loadMcpAuth(serverUrl, deps) !== null;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Connects a whole park.
|
|
361
|
+
*
|
|
362
|
+
* Sequential on purpose: the interactive step opens a browser tab, and three
|
|
363
|
+
* tabs at once is not a flow anybody can complete. A failure is recorded and
|
|
364
|
+
* the loop moves on — the measured worst outcome of the previous generation
|
|
365
|
+
* was one malformed server blinding the verification of every other.
|
|
366
|
+
*/
|
|
367
|
+
export async function connectAll(targets, deps = {}) {
|
|
368
|
+
const connect = deps.connectFn ?? connectMcpServer;
|
|
369
|
+
const results = [];
|
|
370
|
+
for (const target of targets) {
|
|
371
|
+
let result;
|
|
372
|
+
try {
|
|
373
|
+
result = await connect(target.url, deps);
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
// `connectMcpServer` is documented as never throwing; this is the belt
|
|
377
|
+
// that keeps a broken entry from ending the loop if it ever does.
|
|
378
|
+
result = {
|
|
379
|
+
server: canonicalMcpUrl(target.url) ?? target.url,
|
|
380
|
+
status: 'failed',
|
|
381
|
+
reason: 'unusable',
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
results.push({ ...result, name: target.name });
|
|
385
|
+
}
|
|
386
|
+
return { results, ok: results.every((result) => result.status !== 'failed') };
|
|
387
|
+
}
|
|
388
|
+
/** What a status means for the exit code and for what the user should do. */
|
|
389
|
+
export function needsAttention(result) {
|
|
390
|
+
return result.status === 'failed';
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/mcp/auth/connect.ts"],"names":[],"mappings":"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"}
|