@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.
Files changed (264) hide show
  1. package/README.md +71 -2
  2. package/dist/api/gateway-request.js +49 -0
  3. package/dist/api/gateway-request.js.map +1 -0
  4. package/dist/api/projects.js +67 -0
  5. package/dist/api/projects.js.map +1 -1
  6. package/dist/api/repository-link.js +157 -0
  7. package/dist/api/repository-link.js.map +1 -0
  8. package/dist/auth/auth-store.js +107 -25
  9. package/dist/auth/auth-store.js.map +1 -1
  10. package/dist/auth/auth.js +21 -0
  11. package/dist/auth/auth.js.map +1 -1
  12. package/dist/clients/cursor.js +5 -1
  13. package/dist/clients/cursor.js.map +1 -1
  14. package/dist/clients/vscode.js +38 -29
  15. package/dist/clients/vscode.js.map +1 -1
  16. package/dist/commands/mcp/allow.js +219 -0
  17. package/dist/commands/mcp/allow.js.map +1 -0
  18. package/dist/commands/mcp/connect.js +337 -0
  19. package/dist/commands/mcp/connect.js.map +1 -0
  20. package/dist/commands/mcp/index.js +170 -0
  21. package/dist/commands/mcp/index.js.map +1 -0
  22. package/dist/commands/mcp/proxy.js +320 -0
  23. package/dist/commands/mcp/proxy.js.map +1 -0
  24. package/dist/commands/mcp/scan.js +349 -0
  25. package/dist/commands/mcp/scan.js.map +1 -0
  26. package/dist/commands/mcp/sync.js +215 -0
  27. package/dist/commands/mcp/sync.js.map +1 -0
  28. package/dist/config.js +6 -0
  29. package/dist/config.js.map +1 -1
  30. package/dist/diagnostics.js +78 -12
  31. package/dist/diagnostics.js.map +1 -1
  32. package/dist/doctor.js +19 -0
  33. package/dist/doctor.js.map +1 -1
  34. package/dist/guards-evaluator/analysis-types.js +27 -0
  35. package/dist/guards-evaluator/analysis-types.js.map +1 -0
  36. package/dist/guards-evaluator/command-analysis.js +572 -0
  37. package/dist/guards-evaluator/command-analysis.js.map +1 -0
  38. package/dist/guards-evaluator/command-view.js +586 -0
  39. package/dist/guards-evaluator/command-view.js.map +1 -0
  40. package/dist/guards-evaluator/env.js +11 -0
  41. package/dist/guards-evaluator/env.js.map +1 -0
  42. package/dist/guards-evaluator/evaluate.js +91 -41
  43. package/dist/guards-evaluator/evaluate.js.map +1 -1
  44. package/dist/guards-evaluator/index.js +2 -1
  45. package/dist/guards-evaluator/index.js.map +1 -1
  46. package/dist/guards-evaluator/inline-code.js +259 -0
  47. package/dist/guards-evaluator/inline-code.js.map +1 -0
  48. package/dist/guards-evaluator/normalize.js +716 -0
  49. package/dist/guards-evaluator/normalize.js.map +1 -0
  50. package/dist/guards-evaluator/preprocess.js +13 -5
  51. package/dist/guards-evaluator/preprocess.js.map +1 -1
  52. package/dist/guards-evaluator/redact.js +19 -0
  53. package/dist/guards-evaluator/redact.js.map +1 -1
  54. package/dist/guards-evaluator/regex.js +25 -3
  55. package/dist/guards-evaluator/regex.js.map +1 -1
  56. package/dist/guards-evaluator/safe-commands.js +155 -0
  57. package/dist/guards-evaluator/safe-commands.js.map +1 -0
  58. package/dist/guards-evaluator/triage.js +315 -0
  59. package/dist/guards-evaluator/triage.js.map +1 -0
  60. package/dist/hook-runner.js +24679 -5079
  61. package/dist/hooks/install.js +38 -0
  62. package/dist/hooks/install.js.map +1 -1
  63. package/dist/hooks/runtime/config.js +38 -0
  64. package/dist/hooks/runtime/config.js.map +1 -1
  65. package/dist/hooks/runtime/emit.js +94 -61
  66. package/dist/hooks/runtime/emit.js.map +1 -1
  67. package/dist/hooks/runtime/fetch-rules.js +22 -7
  68. package/dist/hooks/runtime/fetch-rules.js.map +1 -1
  69. package/dist/hooks/runtime/gateway-http-error.js +34 -0
  70. package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
  71. package/dist/hooks/runtime/guard-rules-cache.js +139 -17
  72. package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
  73. package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
  74. package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
  75. package/dist/hooks/runtime/judge-cache.js +6 -0
  76. package/dist/hooks/runtime/judge-cache.js.map +1 -1
  77. package/dist/hooks/runtime/judge-triage.js +193 -0
  78. package/dist/hooks/runtime/judge-triage.js.map +1 -0
  79. package/dist/hooks/runtime/judge.js +7 -1
  80. package/dist/hooks/runtime/judge.js.map +1 -1
  81. package/dist/hooks/runtime/pre-compact.js +12 -6
  82. package/dist/hooks/runtime/pre-compact.js.map +1 -1
  83. package/dist/hooks/runtime/resolve.js +90 -8
  84. package/dist/hooks/runtime/resolve.js.map +1 -1
  85. package/dist/hooks/runtime/retry-policy.js +57 -0
  86. package/dist/hooks/runtime/retry-policy.js.map +1 -0
  87. package/dist/hooks/runtime/review-sessions.js +74 -0
  88. package/dist/hooks/runtime/review-sessions.js.map +1 -0
  89. package/dist/hooks/runtime/script-resolve.js +695 -0
  90. package/dist/hooks/runtime/script-resolve.js.map +1 -0
  91. package/dist/hooks/runtime/session-activation.js +5 -1
  92. package/dist/hooks/runtime/session-activation.js.map +1 -1
  93. package/dist/hooks/runtime/session-review.js +163 -45
  94. package/dist/hooks/runtime/session-review.js.map +1 -1
  95. package/dist/hooks/runtime/session-start.js +2 -1
  96. package/dist/hooks/runtime/session-start.js.map +1 -1
  97. package/dist/hooks/runtime/session-writes.js +232 -0
  98. package/dist/hooks/runtime/session-writes.js.map +1 -0
  99. package/dist/hooks/runtime/sniff.js +26 -7
  100. package/dist/hooks/runtime/sniff.js.map +1 -1
  101. package/dist/hooks/runtime/target-resolve.js +336 -0
  102. package/dist/hooks/runtime/target-resolve.js.map +1 -0
  103. package/dist/hooks/runtime/unmapped-tools.js +93 -0
  104. package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
  105. package/dist/hooks/runtime/usage-block.js +4 -0
  106. package/dist/hooks/runtime/usage-block.js.map +1 -1
  107. package/dist/hooks/runtime/user-prompt-submit.js +2 -1
  108. package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
  109. package/dist/hooks/runtime/wire-text.js +41 -0
  110. package/dist/hooks/runtime/wire-text.js.map +1 -0
  111. package/dist/hooks/runtime/work-dir.js +84 -0
  112. package/dist/hooks/runtime/work-dir.js.map +1 -0
  113. package/dist/index.js +45 -12
  114. package/dist/index.js.map +1 -1
  115. package/dist/install.js +174 -11
  116. package/dist/install.js.map +1 -1
  117. package/dist/link.js +74 -48
  118. package/dist/link.js.map +1 -1
  119. package/dist/login.js +77 -11
  120. package/dist/login.js.map +1 -1
  121. package/dist/mcp/auth/agent-sign-ins.js +174 -0
  122. package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
  123. package/dist/mcp/auth/callback.js +200 -0
  124. package/dist/mcp/auth/callback.js.map +1 -0
  125. package/dist/mcp/auth/connect.js +392 -0
  126. package/dist/mcp/auth/connect.js.map +1 -0
  127. package/dist/mcp/auth/discovery.js +399 -0
  128. package/dist/mcp/auth/discovery.js.map +1 -0
  129. package/dist/mcp/auth/oauth.js +326 -0
  130. package/dist/mcp/auth/oauth.js.map +1 -0
  131. package/dist/mcp/auth/probe.js +128 -0
  132. package/dist/mcp/auth/probe.js.map +1 -0
  133. package/dist/mcp/auth/secrets.js +446 -0
  134. package/dist/mcp/auth/secrets.js.map +1 -0
  135. package/dist/mcp/auth/store.js +260 -0
  136. package/dist/mcp/auth/store.js.map +1 -0
  137. package/dist/mcp/auth/tokenSource.js +55 -0
  138. package/dist/mcp/auth/tokenSource.js.map +1 -0
  139. package/dist/mcp/config/atomicWrite.js +98 -0
  140. package/dist/mcp/config/atomicWrite.js.map +1 -0
  141. package/dist/mcp/config/clients.js +171 -0
  142. package/dist/mcp/config/clients.js.map +1 -0
  143. package/dist/mcp/config/cybedefend-servers.js +48 -0
  144. package/dist/mcp/config/cybedefend-servers.js.map +1 -0
  145. package/dist/mcp/config/discover.js +114 -0
  146. package/dist/mcp/config/discover.js.map +1 -0
  147. package/dist/mcp/config/hook.js +123 -0
  148. package/dist/mcp/config/hook.js.map +1 -0
  149. package/dist/mcp/config/index.js +11 -0
  150. package/dist/mcp/config/index.js.map +1 -0
  151. package/dist/mcp/config/install.js +132 -0
  152. package/dist/mcp/config/install.js.map +1 -0
  153. package/dist/mcp/config/installed.js +37 -0
  154. package/dist/mcp/config/installed.js.map +1 -0
  155. package/dist/mcp/config/jsonEdit.js +119 -0
  156. package/dist/mcp/config/jsonEdit.js.map +1 -0
  157. package/dist/mcp/config/lock.js +102 -0
  158. package/dist/mcp/config/lock.js.map +1 -0
  159. package/dist/mcp/config/proxyBinary.js +211 -0
  160. package/dist/mcp/config/proxyBinary.js.map +1 -0
  161. package/dist/mcp/config/rewrite.js +388 -0
  162. package/dist/mcp/config/rewrite.js.map +1 -0
  163. package/dist/mcp/config/types.js +34 -0
  164. package/dist/mcp/config/types.js.map +1 -0
  165. package/dist/mcp/proxy/audit.js +83 -0
  166. package/dist/mcp/proxy/audit.js.map +1 -0
  167. package/dist/mcp/proxy/authInterceptor.js +119 -0
  168. package/dist/mcp/proxy/authInterceptor.js.map +1 -0
  169. package/dist/mcp/proxy/expand.js +93 -0
  170. package/dist/mcp/proxy/expand.js.map +1 -0
  171. package/dist/mcp/proxy/inject.js +412 -0
  172. package/dist/mcp/proxy/inject.js.map +1 -0
  173. package/dist/mcp/proxy/intercept.js +63 -0
  174. package/dist/mcp/proxy/intercept.js.map +1 -0
  175. package/dist/mcp/proxy/jsonrpc.js +153 -0
  176. package/dist/mcp/proxy/jsonrpc.js.map +1 -0
  177. package/dist/mcp/proxy/log.js +109 -0
  178. package/dist/mcp/proxy/log.js.map +1 -0
  179. package/dist/mcp/proxy/paths.js +57 -0
  180. package/dist/mcp/proxy/paths.js.map +1 -0
  181. package/dist/mcp/proxy/proxy.js +520 -0
  182. package/dist/mcp/proxy/proxy.js.map +1 -0
  183. package/dist/mcp/proxy/serverCheckTimer.js +75 -0
  184. package/dist/mcp/proxy/serverCheckTimer.js.map +1 -0
  185. package/dist/mcp/proxy/sessionLifecycle.js +29 -0
  186. package/dist/mcp/proxy/sessionLifecycle.js.map +1 -0
  187. package/dist/mcp/proxy/spec.js +203 -0
  188. package/dist/mcp/proxy/spec.js.map +1 -0
  189. package/dist/mcp/proxy/sse.js +77 -0
  190. package/dist/mcp/proxy/sse.js.map +1 -0
  191. package/dist/mcp/proxy/upstream.js +2 -0
  192. package/dist/mcp/proxy/upstream.js.map +1 -0
  193. package/dist/mcp/proxy/upstreamHttp.js +499 -0
  194. package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
  195. package/dist/mcp/proxy/upstreamStdio.js +188 -0
  196. package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
  197. package/dist/mcp/proxy/upstreams.js +143 -0
  198. package/dist/mcp/proxy/upstreams.js.map +1 -0
  199. package/dist/mcp/proxy/verifyInterceptor.js +718 -0
  200. package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
  201. package/dist/mcp/proxy/windowsCommand.js +99 -0
  202. package/dist/mcp/proxy/windowsCommand.js.map +1 -0
  203. package/dist/mcp/report/buffer.js +351 -0
  204. package/dist/mcp/report/buffer.js.map +1 -0
  205. package/dist/mcp/report/coalesce.js +165 -0
  206. package/dist/mcp/report/coalesce.js.map +1 -0
  207. package/dist/mcp/report/constants.js +51 -0
  208. package/dist/mcp/report/constants.js.map +1 -0
  209. package/dist/mcp/report/project.js +83 -0
  210. package/dist/mcp/report/project.js.map +1 -0
  211. package/dist/mcp/report/reporter.js +443 -0
  212. package/dist/mcp/report/reporter.js.map +1 -0
  213. package/dist/mcp/report/types.js +3 -0
  214. package/dist/mcp/report/types.js.map +1 -0
  215. package/dist/mcp/report/validate.js +179 -0
  216. package/dist/mcp/report/validate.js.map +1 -0
  217. package/dist/mcp/scan/args.js +228 -0
  218. package/dist/mcp/scan/args.js.map +1 -0
  219. package/dist/mcp/scan/results.js +253 -0
  220. package/dist/mcp/scan/results.js.map +1 -0
  221. package/dist/mcp/scan/types.js +40 -0
  222. package/dist/mcp/scan/types.js.map +1 -0
  223. package/dist/mcp/verify/api.js +514 -0
  224. package/dist/mcp/verify/api.js.map +1 -0
  225. package/dist/mcp/verify/backend.js +143 -0
  226. package/dist/mcp/verify/backend.js.map +1 -0
  227. package/dist/mcp/verify/cache.js +200 -0
  228. package/dist/mcp/verify/cache.js.map +1 -0
  229. package/dist/mcp/verify/contract-errors.js +198 -0
  230. package/dist/mcp/verify/contract-errors.js.map +1 -0
  231. package/dist/mcp/verify/digest.js +91 -0
  232. package/dist/mcp/verify/digest.js.map +1 -0
  233. package/dist/mcp/verify/factory.js +56 -0
  234. package/dist/mcp/verify/factory.js.map +1 -0
  235. package/dist/mcp/verify/identity.js +286 -0
  236. package/dist/mcp/verify/identity.js.map +1 -0
  237. package/dist/mcp/verify/policy-store.js +63 -0
  238. package/dist/mcp/verify/policy-store.js.map +1 -0
  239. package/dist/mcp/verify/policy.js +160 -0
  240. package/dist/mcp/verify/policy.js.map +1 -0
  241. package/dist/mcp/verify/pool.js +27 -0
  242. package/dist/mcp/verify/pool.js.map +1 -0
  243. package/dist/mcp/verify/token-refresh.js +44 -0
  244. package/dist/mcp/verify/token-refresh.js.map +1 -0
  245. package/dist/mcp/verify/token.js +67 -0
  246. package/dist/mcp/verify/token.js.map +1 -0
  247. package/dist/mcp/verify/verifier.js +1166 -0
  248. package/dist/mcp/verify/verifier.js.map +1 -0
  249. package/dist/org-gate.js +1 -1
  250. package/dist/org-gate.js.map +1 -1
  251. package/dist/org.js +146 -0
  252. package/dist/org.js.map +1 -0
  253. package/dist/project-create.js +129 -0
  254. package/dist/project-create.js.map +1 -0
  255. package/dist/prompts.js +21 -0
  256. package/dist/prompts.js.map +1 -1
  257. package/dist/re2.wasm +0 -0
  258. package/dist/status.js +61 -0
  259. package/dist/status.js.map +1 -1
  260. package/dist/uninstall.js +49 -4
  261. package/dist/uninstall.js.map +1 -1
  262. package/dist/utils.js +62 -6
  263. package/dist/utils.js.map +1 -1
  264. 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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"}