@codemem/mcp 0.31.4 → 0.32.1

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 (46) hide show
  1. package/dist/audit.d.ts +54 -0
  2. package/dist/audit.d.ts.map +1 -0
  3. package/dist/content.d.ts +13 -0
  4. package/dist/content.d.ts.map +1 -0
  5. package/dist/http.d.ts +38 -0
  6. package/dist/http.d.ts.map +1 -0
  7. package/dist/http.js +1049 -0
  8. package/dist/http.js.map +1 -0
  9. package/dist/index.d.ts +2 -10
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -602
  12. package/dist/memory-access.d.ts.map +1 -1
  13. package/dist/memory-kinds.d.ts +2 -0
  14. package/dist/memory-kinds.d.ts.map +1 -0
  15. package/dist/oauth.d.ts +176 -0
  16. package/dist/oauth.d.ts.map +1 -0
  17. package/dist/oidc.d.ts +35 -0
  18. package/dist/oidc.d.ts.map +1 -0
  19. package/dist/project-scope.d.ts +4 -0
  20. package/dist/project-scope.d.ts.map +1 -1
  21. package/dist/provider.d.ts +51 -0
  22. package/dist/provider.d.ts.map +1 -0
  23. package/dist/schemas.d.ts +36 -0
  24. package/dist/schemas.d.ts.map +1 -0
  25. package/dist/server-Djvf0Yik.js +488 -0
  26. package/dist/server-Djvf0Yik.js.map +1 -0
  27. package/dist/server.d.ts +5 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/stdio.d.ts +9 -0
  30. package/dist/stdio.d.ts.map +1 -0
  31. package/dist/stdio.js +69 -0
  32. package/dist/stdio.js.map +1 -0
  33. package/dist/tool-context.d.ts +12 -0
  34. package/dist/tool-context.d.ts.map +1 -0
  35. package/dist/tools/items.d.ts +4 -0
  36. package/dist/tools/items.d.ts.map +1 -0
  37. package/dist/tools/learn.d.ts +3 -0
  38. package/dist/tools/learn.d.ts.map +1 -0
  39. package/dist/tools/schema.d.ts +3 -0
  40. package/dist/tools/schema.d.ts.map +1 -0
  41. package/dist/tools/search.d.ts +4 -0
  42. package/dist/tools/search.d.ts.map +1 -0
  43. package/dist/tools/timeline.d.ts +4 -0
  44. package/dist/tools/timeline.d.ts.map +1 -0
  45. package/package.json +19 -7
  46. package/dist/index.js.map +0 -1
package/dist/http.js ADDED
@@ -0,0 +1,1049 @@
1
+ #!/usr/bin/env node
2
+ import { t as e } from "./server-Djvf0Yik.js";
3
+ import { createServer as t } from "node:http";
4
+ import { isIP as n } from "node:net";
5
+ import { pathToFileURL as r } from "node:url";
6
+ import { MemoryStore as i, resolveDbPath as a } from "@codemem/core";
7
+ import { requireBearerAuth as o } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
8
+ import { createOAuthMetadata as s, getOAuthProtectedResourceMetadataUrl as c, mcpAuthRouter as l } from "@modelcontextprotocol/sdk/server/auth/router.js";
9
+ import { StreamableHTTPServerTransport as u } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
10
+ import d from "express";
11
+ import { createHmac as f, createPublicKey as p, randomBytes as m, randomUUID as h, timingSafeEqual as g, verify as _ } from "node:crypto";
12
+ import { AccessDeniedError as v, InvalidClientError as y, InvalidClientMetadataError as b, InvalidGrantError as x, InvalidRequestError as S, InvalidTokenError as C, ServerError as w, TemporarilyUnavailableError as T, UnsupportedResponseTypeError as E } from "@modelcontextprotocol/sdk/server/auth/errors.js";
13
+ import { OAuthProtectedResourceMetadataSchema as D, OAuthTokensSchema as O } from "@modelcontextprotocol/sdk/shared/auth.js";
14
+ //#region src/audit.ts
15
+ var k = new Set([
16
+ "token",
17
+ "accesstoken",
18
+ "refreshtoken",
19
+ "idtoken",
20
+ "code",
21
+ "codeverifier",
22
+ "codechallenge",
23
+ "clientsecret",
24
+ "authorization",
25
+ "password",
26
+ "secret"
27
+ ]);
28
+ function ee(e) {
29
+ return e.toLowerCase().replace(/[^a-z0-9]/g, "");
30
+ }
31
+ function A(e, t) {
32
+ for (let e of Object.keys(t)) if (k.has(ee(e))) throw Error(`OAuth audit event must not carry forbidden field: ${e}`);
33
+ let { now: n, ...r } = t;
34
+ return {
35
+ kind: e,
36
+ timestamp: new Date(n ?? Date.now()).toISOString(),
37
+ ...r
38
+ };
39
+ }
40
+ function te(e) {
41
+ let t = !1;
42
+ return (n) => {
43
+ try {
44
+ e(n);
45
+ } catch (e) {
46
+ t || (t = !0, console.error("codemem MCP OAuth audit emitter failed (further failures suppressed):", e));
47
+ }
48
+ };
49
+ }
50
+ function ne(e = process.stderr) {
51
+ return (t) => {
52
+ e.write(`${JSON.stringify({
53
+ source: "codemem-mcp-oauth-audit",
54
+ ...t
55
+ })}\n`);
56
+ };
57
+ }
58
+ function re() {
59
+ return () => {};
60
+ }
61
+ function ie(e = process.env.CODEMEM_MCP_AUDIT) {
62
+ let t = e?.trim().toLowerCase();
63
+ return t === "0" || t === "false" || t === "no" ? re() : ne();
64
+ }
65
+ var ae = "codemem MCP", j = ["memory:read", "memory:write"], M = "https://github.com/kunickiaj/codemem#readme", oe = "https://claude.ai/api/mcp/auth_callback", N = new Set([
66
+ "localhost",
67
+ "127.0.0.1",
68
+ "::1"
69
+ ]), se = new Set(["authorization_code", "refresh_token"]), ce = new Set(["code"]), P = 3600, F = 720 * 60 * 60, le = 100, ue = 100, de = 100, I = 32, fe = 43, pe = /^[A-Za-z0-9_-]{43}$/, me = /^[A-Za-z0-9_-]{43}$/, he = class {
70
+ #e = /* @__PURE__ */ new Map();
71
+ getClient(e) {
72
+ return this.#e.get(e);
73
+ }
74
+ registerClient(e) {
75
+ let t = De(e.redirect_uris);
76
+ if (t) throw new b(t);
77
+ if (e.client_secret || e.token_endpoint_auth_method !== "none") throw new b("Only public clients with token_endpoint_auth_method=none are supported");
78
+ if (e.grant_types && !Oe(e.grant_types, se)) throw new b("Only authorization_code and refresh_token grant_types are supported");
79
+ if (e.response_types && !Oe(e.response_types, ce)) throw new b("Only code response_type is supported");
80
+ if (this.#e.size >= 100) {
81
+ let e = this.#e.keys().next().value;
82
+ e && this.#e.delete(e);
83
+ }
84
+ let n = {
85
+ ...e,
86
+ token_endpoint_auth_method: "none",
87
+ grant_types: e.grant_types ?? ["authorization_code", "refresh_token"],
88
+ response_types: e.response_types ?? ["code"],
89
+ client_id: h(),
90
+ client_id_issued_at: Math.floor(Date.now() / 1e3)
91
+ };
92
+ return this.#e.set(n.client_id, n), n;
93
+ }
94
+ }, ge = class {
95
+ #e = /* @__PURE__ */ new Map();
96
+ issueCode(e, t = Date.now()) {
97
+ if (this.#t(t), this.#e.size >= le) return;
98
+ let n = h();
99
+ return this.#e.set(n, {
100
+ ...e,
101
+ used: !1
102
+ }), n;
103
+ }
104
+ peekCode(e) {
105
+ let t = this.#e.get(e);
106
+ if (!(!t || t.used)) return t;
107
+ }
108
+ consumeCode(e) {
109
+ let t = this.#e.get(e);
110
+ if (!(!t || t.used)) return t.used = !0, t;
111
+ }
112
+ #t(e) {
113
+ for (let [t, n] of this.#e) n.expiresAt <= e && this.#e.delete(t);
114
+ }
115
+ }, _e = class {
116
+ #e = /* @__PURE__ */ new Map();
117
+ #t = m(32);
118
+ issueToken(e, t = Date.now(), n, r, i = []) {
119
+ if (this.#n(t), this.#e.size >= ue) return;
120
+ let a = m(I), o = V(a, this.#t);
121
+ return this.#e.set(o, {
122
+ clientId: e,
123
+ grantId: r,
124
+ scopes: [...i],
125
+ resource: n,
126
+ tokenHash: o,
127
+ issuedAt: t,
128
+ expiresAt: t + P * 1e3,
129
+ lastUsedAt: null,
130
+ revokedAt: null
131
+ }), {
132
+ token: a.toString("base64url"),
133
+ expiresIn: P
134
+ };
135
+ }
136
+ verifyToken(e, t = Date.now()) {
137
+ let n = z(e);
138
+ if (!n) return {
139
+ ok: !1,
140
+ reason: "unknown_token"
141
+ };
142
+ let r = V(n, this.#t), i = this.#e.get(r);
143
+ return !i || !U(i.tokenHash, r) ? {
144
+ ok: !1,
145
+ reason: "unknown_token"
146
+ } : i.revokedAt === null ? i.expiresAt <= t ? {
147
+ ok: !1,
148
+ reason: "expired_token"
149
+ } : (i.lastUsedAt = t, {
150
+ ok: !0,
151
+ record: { ...i }
152
+ }) : {
153
+ ok: !1,
154
+ reason: "revoked_token"
155
+ };
156
+ }
157
+ revokeToken(e, t = Date.now()) {
158
+ let n = z(e);
159
+ if (!n) return !1;
160
+ let r = V(n, this.#t), i = this.#e.get(r);
161
+ return !i || !U(i.tokenHash, r) ? !1 : (i.revokedAt === null && (i.revokedAt = t), !0);
162
+ }
163
+ revokeTokensForGrant(e, t = Date.now()) {
164
+ let n = 0;
165
+ for (let r of this.#e.values()) r.grantId !== e || r.revokedAt !== null || (r.revokedAt = t, n += 1);
166
+ return n;
167
+ }
168
+ #n(e) {
169
+ for (let [t, n] of this.#e) (n.expiresAt <= e || n.revokedAt !== null) && this.#e.delete(t);
170
+ }
171
+ }, ve = class {
172
+ #e = /* @__PURE__ */ new Map();
173
+ #t = /* @__PURE__ */ new Map();
174
+ #n = /* @__PURE__ */ new Map();
175
+ #r = m(32);
176
+ issueGrant(e, t = Date.now()) {
177
+ if (this.#i(t), this.#e.size >= de) return;
178
+ let n = Pe(), r = B(n, this.#r);
179
+ if (!r) return;
180
+ let i = {
181
+ grantId: h(),
182
+ clientId: e.clientId,
183
+ scopes: [...e.scopes ?? []],
184
+ resource: e.resource,
185
+ currentRefreshTokenHash: r,
186
+ previousRefreshTokenHash: null,
187
+ issuedAt: t,
188
+ expiresAt: t + F * 1e3,
189
+ rotatedAt: null,
190
+ revokedAt: null
191
+ };
192
+ return this.#e.set(i.grantId, i), this.#t.set(r, i.grantId), this.#n.set(i.grantId, new Set([r])), {
193
+ grant: {
194
+ ...i,
195
+ scopes: [...i.scopes]
196
+ },
197
+ refreshToken: n,
198
+ expiresIn: F
199
+ };
200
+ }
201
+ rotateRefreshToken(e, t, n = {}, r = Date.now()) {
202
+ let i = B(t, this.#r);
203
+ if (!i) return {
204
+ ok: !1,
205
+ reason: "unknown_refresh_token"
206
+ };
207
+ let a = this.#t.get(i);
208
+ if (!a) return {
209
+ ok: !1,
210
+ reason: "unknown_refresh_token"
211
+ };
212
+ let o = this.#e.get(a);
213
+ if (!o) return {
214
+ ok: !1,
215
+ reason: "unknown_refresh_token"
216
+ };
217
+ if (o.revokedAt !== null) return {
218
+ ok: !1,
219
+ reason: "revoked_refresh_token",
220
+ grantId: a
221
+ };
222
+ if (o.expiresAt <= r) return this.revokeGrant(a, r), {
223
+ ok: !1,
224
+ reason: "expired_refresh_token",
225
+ grantId: a
226
+ };
227
+ if (o.clientId !== e) return {
228
+ ok: !1,
229
+ reason: "client_mismatch",
230
+ grantId: a
231
+ };
232
+ if (!Fe(n.scopes ?? o.scopes, o.scopes)) return {
233
+ ok: !1,
234
+ reason: "scope_mismatch",
235
+ grantId: a
236
+ };
237
+ if ((o.resource ?? null) !== (n.resource ?? o.resource ?? null)) return {
238
+ ok: !1,
239
+ reason: "resource_mismatch",
240
+ grantId: a
241
+ };
242
+ let s = U(o.currentRefreshTokenHash, i), c = o.previousRefreshTokenHash !== null && U(o.previousRefreshTokenHash, i);
243
+ if (!s && !c) return this.revokeGrant(a, r), {
244
+ ok: !1,
245
+ reason: "refresh_token_replay",
246
+ grantId: a
247
+ };
248
+ let l = Pe(), u = B(l, this.#r);
249
+ return u ? (o.scopes = [...n.scopes ?? o.scopes], o.previousRefreshTokenHash = s ? o.currentRefreshTokenHash : null, o.currentRefreshTokenHash = u, o.rotatedAt = r, this.#t.set(u, a), this.#n.get(a)?.add(u), {
250
+ ok: !0,
251
+ grant: {
252
+ ...o,
253
+ scopes: [...o.scopes]
254
+ },
255
+ refreshToken: l,
256
+ expiresIn: Math.max(0, Math.floor((o.expiresAt - r) / 1e3))
257
+ }) : {
258
+ ok: !1,
259
+ reason: "unknown_refresh_token"
260
+ };
261
+ }
262
+ revokeRefreshToken(e, t = Date.now()) {
263
+ let n = B(e, this.#r);
264
+ if (!n) return;
265
+ let r = this.#t.get(n);
266
+ if (r) return this.revokeGrant(r, t), r;
267
+ }
268
+ revokeGrant(e, t = Date.now()) {
269
+ let n = this.#e.get(e);
270
+ return n ? n.revokedAt === null ? (n.revokedAt = t, this.#a(n), !0) : !0 : !1;
271
+ }
272
+ #i(e) {
273
+ for (let [t, n] of this.#e) n.expiresAt > e && n.revokedAt === null || (this.#e.delete(t), this.#a(n));
274
+ }
275
+ #a(e) {
276
+ let t = this.#n.get(e.grantId);
277
+ if (t) {
278
+ for (let e of t) this.#t.delete(e);
279
+ this.#n.delete(e.grantId);
280
+ return;
281
+ }
282
+ this.#t.delete(e.currentRefreshTokenHash), e.previousRefreshTokenHash && this.#t.delete(e.previousRefreshTokenHash);
283
+ }
284
+ };
285
+ function ye() {
286
+ return new he();
287
+ }
288
+ function be() {
289
+ return new ge();
290
+ }
291
+ function xe() {
292
+ return new _e();
293
+ }
294
+ function Se() {
295
+ return new ve();
296
+ }
297
+ function Ce(e) {
298
+ let t = Ee(L(e.mcpUrl));
299
+ return {
300
+ ...s({
301
+ provider: Ie(e.clientsStore),
302
+ issuerUrl: t,
303
+ baseUrl: t
304
+ }),
305
+ grant_types_supported: ["authorization_code", "refresh_token"],
306
+ token_endpoint_auth_methods_supported: ["none"],
307
+ scopes_supported: j,
308
+ service_documentation: M,
309
+ revocation_endpoint: new URL("/revoke", t).href,
310
+ revocation_endpoint_auth_methods_supported: ["none"],
311
+ client_id_metadata_document_supported: !1
312
+ };
313
+ }
314
+ function we(e) {
315
+ let t = L(e), n = {
316
+ resource: t.href,
317
+ authorization_servers: [Ee(t).href],
318
+ scopes_supported: j,
319
+ bearer_methods_supported: ["header"],
320
+ resource_name: ae,
321
+ resource_documentation: M
322
+ };
323
+ return D.parse(n);
324
+ }
325
+ function Te(e, t) {
326
+ let n = e.get("client_id") ?? "", r = e.get("redirect_uri") ?? "", i = e.get("response_type") ?? "", a = e.get("code_challenge") ?? "", o = e.get("code_challenge_method") ?? "", s = e.get("resource"), c = Me(e.get("scope")), l = e.get("state");
327
+ if (i !== "code") return R("unsupported_response_type");
328
+ if (o !== "S256") return R("invalid_request", "PKCE code_challenge_method=S256 is required");
329
+ if (!me.test(a)) return R("invalid_request", "Valid PKCE S256 code_challenge is required");
330
+ let u = Ne(t, n);
331
+ return u ? u.redirect_uris.includes(r) ? {
332
+ clientId: n,
333
+ redirectUri: r,
334
+ codeChallenge: a,
335
+ scopes: c,
336
+ resource: s,
337
+ state: l
338
+ } : R("invalid_request", "redirect_uri is not registered for this client") : R("invalid_client", "Unknown OAuth client_id");
339
+ }
340
+ function L(e) {
341
+ let t;
342
+ try {
343
+ t = new URL(e);
344
+ } catch {
345
+ throw Error("Invalid MCP HTTP public URL; expected an HTTPS /mcp URL");
346
+ }
347
+ if (t.protocol !== "https:" && !Ae(t)) throw Error("Invalid MCP HTTP public URL; use HTTPS for non-loopback URLs");
348
+ if (t.username || t.password || t.search || t.hash) throw Error("Invalid MCP HTTP public URL; credentials, query strings, and fragments are not allowed");
349
+ if (t.pathname === "/" && (t.pathname = "/mcp"), t.pathname !== "/mcp") throw Error("Invalid MCP HTTP public URL; expected /mcp path");
350
+ return t;
351
+ }
352
+ function Ee(e) {
353
+ return new URL(e.origin);
354
+ }
355
+ function De(e) {
356
+ for (let t of e) {
357
+ let e = new URL(t);
358
+ if (e.username || e.password || e.hash) return `Invalid redirect URI: ${t}`;
359
+ if (e.href !== oe && !ke(e)) return `Unsupported redirect URI: ${t}`;
360
+ }
361
+ return null;
362
+ }
363
+ function Oe(e, t) {
364
+ return e.length > 0 && e.every((e) => t.has(e));
365
+ }
366
+ function ke(e) {
367
+ return e.protocol === "http:" && N.has(je(e.hostname)) && e.pathname === "/callback" && e.search === "";
368
+ }
369
+ function Ae(e) {
370
+ let t = je(e.hostname);
371
+ return e.protocol === "http:" && N.has(t);
372
+ }
373
+ function je(e) {
374
+ return e.replace(/^\[(.*)]$/, "$1").toLowerCase();
375
+ }
376
+ function Me(e) {
377
+ return e?.split(/\s+/).map((e) => e.trim()).filter(Boolean) ?? [];
378
+ }
379
+ function R(e, t) {
380
+ return {
381
+ status: 400,
382
+ body: t ? {
383
+ error: e,
384
+ error_description: t
385
+ } : { error: e }
386
+ };
387
+ }
388
+ function Ne(e, t) {
389
+ let n = e.getClient(t);
390
+ if (n instanceof Promise) throw Error("Asynchronous OAuth client stores are not supported by this HTTP bootstrap yet");
391
+ return n;
392
+ }
393
+ function z(e) {
394
+ if (typeof e != "string" || e.length !== fe || !pe.test(e)) return null;
395
+ let t = Buffer.from(e, "base64url");
396
+ return t.length === I ? t : null;
397
+ }
398
+ function Pe() {
399
+ return m(I).toString("base64url");
400
+ }
401
+ function B(e, t) {
402
+ let n = z(e);
403
+ return n ? H(n, t) : null;
404
+ }
405
+ function V(e, t) {
406
+ return H(e, t);
407
+ }
408
+ function H(e, t) {
409
+ return f("sha256", t).update(e).digest("base64url");
410
+ }
411
+ function U(e, t) {
412
+ let n = Buffer.from(e), r = Buffer.from(t);
413
+ return n.length === r.length && g(n, r);
414
+ }
415
+ function Fe(e, t) {
416
+ let n = new Set(t);
417
+ return e.every((e) => n.has(e));
418
+ }
419
+ function Ie(e) {
420
+ return {
421
+ clientsStore: e,
422
+ async authorize() {
423
+ throw Error("OAuth authorize is not implemented yet");
424
+ },
425
+ async challengeForAuthorizationCode() {
426
+ throw Error("OAuth token exchange is not implemented yet");
427
+ },
428
+ async exchangeAuthorizationCode() {
429
+ throw Error("OAuth token exchange is not implemented yet");
430
+ },
431
+ async exchangeRefreshToken() {
432
+ throw Error("OAuth refresh is not implemented yet");
433
+ },
434
+ async verifyAccessToken() {
435
+ throw Error("OAuth bearer verification is not implemented yet");
436
+ }
437
+ };
438
+ }
439
+ //#endregion
440
+ //#region src/oidc.ts
441
+ var Le = "CODEMEM_MCP_OIDC_ISSUER_URL", Re = "CODEMEM_MCP_OIDC_CLIENT_ID", ze = "CODEMEM_MCP_OIDC_CLIENT_SECRET", Be = "CODEMEM_MCP_OAUTH_ALLOWED_SUBJECT", Ve = "CODEMEM_MCP_OAUTH_ALLOWED_EMAIL", He = 300 * 1e3, Ue = 100, We = 300 * 1e3, Ge = class {
442
+ #e = /* @__PURE__ */ new Map();
443
+ issue(e, t = Date.now()) {
444
+ if (this.#t(t), this.#e.size >= Ue) return;
445
+ let n = h();
446
+ return this.#e.set(n, {
447
+ ...e,
448
+ expiresAt: t + He
449
+ }), n;
450
+ }
451
+ consume(e) {
452
+ let t = this.#e.get(e);
453
+ return this.#e.delete(e), t;
454
+ }
455
+ #t(e) {
456
+ for (let [t, n] of this.#e) n.expiresAt <= e && this.#e.delete(t);
457
+ }
458
+ };
459
+ function Ke() {
460
+ return new Ge();
461
+ }
462
+ function qe(e = process.env) {
463
+ let t = e[Le]?.trim(), n = e[Re]?.trim(), r = e[ze]?.trim(), i = e[Be]?.trim(), a = e[Ve]?.trim().toLowerCase();
464
+ if (!(!t && !n && !r && !i && !a)) {
465
+ if (!t || !n || !r) throw Error("Incomplete MCP OIDC configuration");
466
+ if (q(t, "issuer", { allowLoopbackHttp: !0 }), !i && !a) throw Error("MCP OIDC requires CODEMEM_MCP_OAUTH_ALLOWED_SUBJECT or CODEMEM_MCP_OAUTH_ALLOWED_EMAIL");
467
+ return {
468
+ issuerUrl: t,
469
+ clientId: n,
470
+ clientSecret: r,
471
+ allowedSubject: i,
472
+ allowedEmail: a
473
+ };
474
+ }
475
+ }
476
+ async function Je(e, t, n, r, i, a = Date.now()) {
477
+ if (!r) return J("temporarily_unavailable", "OIDC is not configured");
478
+ let o = Te(e, t);
479
+ if ("status" in o) return o;
480
+ let s = await G(r.issuerUrl), c = h(), l = n.issue({
481
+ oauthParams: e.toString(),
482
+ nonce: c
483
+ }, a);
484
+ if (!l) return J("temporarily_unavailable", "Too many pending OIDC authorizations");
485
+ let u = W(i), d = new URL(s.authorization_endpoint);
486
+ return d.searchParams.set("response_type", "code"), d.searchParams.set("client_id", r.clientId), d.searchParams.set("redirect_uri", u), d.searchParams.set("scope", "openid email"), d.searchParams.set("state", l), d.searchParams.set("nonce", c), {
487
+ status: 302,
488
+ location: d.href
489
+ };
490
+ }
491
+ async function Ye(e, t, n, r, i = Date.now()) {
492
+ try {
493
+ let a = e.get("code") ?? "", o = e.get("state") ?? "";
494
+ if (!o) return J("invalid_request", "Missing OIDC state");
495
+ let s = t.consume(o);
496
+ if (!s || s.expiresAt <= i) return J("invalid_request", "Expired or unknown OIDC state");
497
+ if (!a) return J("invalid_request", "Missing OIDC code");
498
+ let c = await G(n.issuerUrl), l = await Xe(c.token_endpoint, n, W(r), a);
499
+ return l.id_token ? et(await Ze(l.id_token, c, n.clientId, s.nonce, i), n) ? { oauthParams: new URLSearchParams(s.oauthParams) } : J("access_denied", "OIDC identity is not allowed") : J("invalid_request", "OIDC token exchange failed");
500
+ } catch {
501
+ return J("access_denied", "OIDC identity verification failed");
502
+ }
503
+ }
504
+ function W(e) {
505
+ let t = new URL(e);
506
+ return new URL("/oauth/callback", t.origin).href;
507
+ }
508
+ async function G(e) {
509
+ let t = new URL(e);
510
+ if (t.search || t.hash) throw Error("OIDC issuer must not include query or fragment");
511
+ if (t.username || t.password) throw Error("OIDC issuer must not include credentials");
512
+ let n = new URL(`${t.pathname.replace(/\/$/, "")}/.well-known/openid-configuration`, t.origin), r = await fetch(n);
513
+ if (!r.ok) throw Error("OIDC discovery request failed");
514
+ let i = await r.json();
515
+ if (i.issuer !== t.href && i.issuer !== t.href.replace(/\/$/, "")) throw Error("OIDC discovery issuer mismatch");
516
+ if (!i.authorization_endpoint || !i.token_endpoint || !i.jwks_uri) throw Error("OIDC discovery metadata is incomplete");
517
+ let a = t.protocol === "http:" && tt(t.hostname);
518
+ return q(i.authorization_endpoint, "authorization endpoint", { allowLoopbackHttp: a }), q(i.token_endpoint, "token endpoint", { allowLoopbackHttp: a }), q(i.jwks_uri, "JWKS URI", { allowLoopbackHttp: a }), i;
519
+ }
520
+ async function Xe(e, t, n, r) {
521
+ let i = new URLSearchParams({
522
+ grant_type: "authorization_code",
523
+ code: r,
524
+ redirect_uri: n,
525
+ client_id: t.clientId,
526
+ client_secret: t.clientSecret
527
+ }), a = await fetch(e, {
528
+ method: "POST",
529
+ headers: { "content-type": "application/x-www-form-urlencoded" },
530
+ body: i
531
+ });
532
+ if (!a.ok) throw Error("OIDC token request failed");
533
+ return await a.json();
534
+ }
535
+ async function Ze(e, t, n, r, i) {
536
+ let [a, o, s] = e.split(".");
537
+ if (!a || !o || !s) throw Error("Invalid OIDC id_token");
538
+ let c = K(a), l = K(o);
539
+ if (c.alg !== "RS256" || !c.kid) throw Error("Unsupported OIDC id_token signature");
540
+ if (l.iss !== t.issuer) throw Error("OIDC id_token issuer mismatch");
541
+ if (!Qe(l.aud, n)) throw Error("OIDC id_token audience mismatch");
542
+ if (!$e(l.aud, l.azp, n)) throw Error("OIDC id_token authorized party mismatch");
543
+ if (typeof l.exp != "number" || !Number.isFinite(l.exp) || l.exp * 1e3 <= i) throw Error("OIDC id_token is expired");
544
+ if (typeof l.iat != "number" || !Number.isFinite(l.iat)) throw Error("OIDC id_token issued-at time is missing");
545
+ if (l.iat * 1e3 > i + We) throw Error("OIDC id_token issued-at time is in the future");
546
+ if (l.nonce !== r) throw Error("OIDC id_token nonce mismatch");
547
+ if (!l.sub) throw Error("OIDC id_token subject is missing");
548
+ let u = await fetch(t.jwks_uri);
549
+ if (!u.ok) throw Error("OIDC JWKS request failed");
550
+ let d = (await u.json()).keys?.find((e) => e.kid === c.kid && e.kty === "RSA");
551
+ if (!d) throw Error("OIDC signing key not found");
552
+ let f = p({
553
+ key: d,
554
+ format: "jwk"
555
+ }), m = `${a}.${o}`;
556
+ if (!_("RSA-SHA256", Buffer.from(m), f, Buffer.from(s, "base64url"))) throw Error("OIDC id_token signature verification failed");
557
+ return l;
558
+ }
559
+ function K(e) {
560
+ return JSON.parse(Buffer.from(e, "base64url").toString("utf8"));
561
+ }
562
+ function Qe(e, t) {
563
+ return Array.isArray(e) ? e.includes(t) : e === t;
564
+ }
565
+ function $e(e, t, n) {
566
+ return t && t !== n ? !1 : !Array.isArray(e) || e.length <= 1 || t === n;
567
+ }
568
+ function et(e, t) {
569
+ return t.allowedSubject && e.sub === t.allowedSubject ? !0 : t.allowedEmail ? e.email_verified === !0 && e.email?.toLowerCase() === t.allowedEmail : !1;
570
+ }
571
+ function q(e, t, n = {}) {
572
+ let r = new URL(e);
573
+ if (r.username || r.password) throw Error(`OIDC ${t} must not include credentials`);
574
+ if (r.protocol !== "https:" && !(n.allowLoopbackHttp && r.protocol === "http:" && tt(r.hostname))) throw Error(`OIDC ${t} must use HTTPS`);
575
+ }
576
+ function tt(e) {
577
+ let t = e.replace(/^\[(.*)]$/, "$1").toLowerCase();
578
+ return t === "localhost" || t === "127.0.0.1" || t === "::1";
579
+ }
580
+ function J(e, t) {
581
+ return {
582
+ status: 400,
583
+ body: t ? {
584
+ error: e,
585
+ error_description: t
586
+ } : { error: e }
587
+ };
588
+ }
589
+ //#endregion
590
+ //#region src/provider.ts
591
+ var nt = class {
592
+ #e;
593
+ #t;
594
+ #n;
595
+ #r;
596
+ #i;
597
+ #a;
598
+ #o;
599
+ #s;
600
+ constructor(e) {
601
+ this.#e = e.clientsStore, this.#t = e.codeStore, this.#n = e.tokenStore, this.#r = e.refreshTokenStore ?? Se(), this.#i = e.publicMcpUrl, this.#a = new URL(e.publicMcpUrl).href, this.#o = e.oidc, this.#s = e.now ?? Date.now;
602
+ }
603
+ get clientsStore() {
604
+ return this.#e;
605
+ }
606
+ async authorize(e, t, n) {
607
+ if (!this.#o) throw new T("OIDC is not configured");
608
+ let r = await Je(rt(e, t), this.#e, this.#o.pendingStore, this.#o.config, this.#i, this.#s());
609
+ if (r.status === 302) {
610
+ n.redirect(302, r.location);
611
+ return;
612
+ }
613
+ throw it(r.body);
614
+ }
615
+ async challengeForAuthorizationCode(e, t) {
616
+ let n = this.#t.peekCode(t);
617
+ if (!n) throw new x("Invalid or already used code");
618
+ if (n.clientId !== e.client_id) throw new x("Code does not match client");
619
+ if (n.expiresAt <= this.#s()) throw this.#t.consumeCode(t), new x("Expired code");
620
+ return n.codeChallenge;
621
+ }
622
+ async exchangeAuthorizationCode(e, t, n, r, i) {
623
+ let a = this.#s(), o = this.#t.peekCode(t);
624
+ if (!o) throw new x("Invalid or already used code");
625
+ if (o.expiresAt <= a) throw this.#t.consumeCode(t), new x("Expired code");
626
+ if (o.clientId !== e.client_id) throw this.#t.consumeCode(t), new x("Code does not match client");
627
+ if (r === void 0 || o.redirectUri !== r) throw this.#t.consumeCode(t), new x("Code does not match redirect_uri");
628
+ if ((o.resource ?? null) !== (i?.href ?? null)) throw this.#t.consumeCode(t), new x("Code does not match resource");
629
+ let s = ot(o.scopes) ?? [], c = this.#r.issueGrant({
630
+ clientId: e.client_id,
631
+ scopes: s,
632
+ resource: o.resource
633
+ }, a);
634
+ if (!c) throw new T("Too many active refresh grants");
635
+ let l = this.#n.issueToken(e.client_id, a, o.resource, c.grant.grantId, s);
636
+ if (!l) throw this.#r.revokeGrant(c.grant.grantId, a), new T("Too many active access tokens");
637
+ if (!this.#t.consumeCode(t)) throw this.#n.revokeToken(l.token, a), this.#r.revokeGrant(c.grant.grantId, a), new x("Authorization code already used");
638
+ return O.parse({
639
+ access_token: l.token,
640
+ token_type: "Bearer",
641
+ expires_in: l.expiresIn,
642
+ refresh_token: c.refreshToken
643
+ });
644
+ }
645
+ async exchangeRefreshToken(e, t, n, r) {
646
+ let i = this.#s(), a = this.#r.rotateRefreshToken(e.client_id, t, {
647
+ scopes: ot(n),
648
+ ...r ? { resource: r.href } : {}
649
+ }, i);
650
+ if (!a.ok) throw a.reason === "refresh_token_replay" && a.grantId && this.#n.revokeTokensForGrant?.(a.grantId, i), new x(at(a.reason));
651
+ let o = this.#n.issueToken(e.client_id, i, a.grant.resource, a.grant.grantId, a.grant.scopes);
652
+ if (!o) throw new T("Too many active access tokens");
653
+ return O.parse({
654
+ access_token: o.token,
655
+ token_type: "Bearer",
656
+ expires_in: o.expiresIn,
657
+ refresh_token: a.refreshToken
658
+ });
659
+ }
660
+ async verifyAccessToken(e) {
661
+ let t = this.#n.verifyToken(e, this.#s());
662
+ if (!t.ok) throw new C(t.reason === "expired_token" ? "Token has expired" : t.reason === "revoked_token" ? "Token has been revoked" : "Token is invalid");
663
+ let n = {
664
+ token: e,
665
+ clientId: t.record.clientId,
666
+ scopes: t.record.scopes,
667
+ expiresAt: Math.floor(t.record.expiresAt / 1e3)
668
+ };
669
+ if (t.record.resource) {
670
+ if (new URL(t.record.resource).href !== this.#a) throw new C("Token audience does not match this resource server");
671
+ n.resource = new URL(t.record.resource);
672
+ }
673
+ return n;
674
+ }
675
+ async revokeToken(e, t) {
676
+ let n = this.#s();
677
+ this.#n.revokeToken(t.token, n);
678
+ let r = this.#r.revokeRefreshToken(t.token, n);
679
+ r && this.#n.revokeTokensForGrant?.(r, n);
680
+ }
681
+ };
682
+ function rt(e, t) {
683
+ let n = new URLSearchParams();
684
+ return n.set("client_id", e.client_id), n.set("redirect_uri", t.redirectUri), n.set("response_type", "code"), n.set("code_challenge", t.codeChallenge), n.set("code_challenge_method", "S256"), t.state && n.set("state", t.state), t.scopes?.length && n.set("scope", t.scopes.join(" ")), t.resource && n.set("resource", t.resource.href), n;
685
+ }
686
+ function it(e) {
687
+ let t = e.error_description ?? e.error;
688
+ switch (e.error) {
689
+ case "temporarily_unavailable": return new T(t);
690
+ case "invalid_request": return new S(t);
691
+ case "invalid_client": return new y(t);
692
+ case "access_denied": return new v(t);
693
+ case "unsupported_response_type": return new E(t);
694
+ default: return new w(t);
695
+ }
696
+ }
697
+ function at(e) {
698
+ switch (e) {
699
+ case "expired_refresh_token": return "Refresh token has expired";
700
+ case "revoked_refresh_token": return "Refresh token has been revoked";
701
+ case "client_mismatch": return "Refresh token does not match client";
702
+ case "scope_mismatch": return "Refresh token scope cannot be expanded";
703
+ case "resource_mismatch": return "Refresh token does not match resource";
704
+ case "refresh_token_replay": return "Refresh token replay detected";
705
+ default: return "Invalid refresh token";
706
+ }
707
+ }
708
+ function ot(e) {
709
+ let t = e?.map((e) => e.trim()).filter(Boolean).map((e) => e === "memory:read_access" ? "memory:read" : e === "memory:write_access" ? "memory:write" : e);
710
+ return t && t.length > 0 ? t : void 0;
711
+ }
712
+ //#endregion
713
+ //#region src/http.ts
714
+ var st = "127.0.0.1", Y = 38889, ct = 80, lt = /^[a-zA-Z0-9.-]+$/, ut = new Set([
715
+ "127.0.0.1",
716
+ "::1",
717
+ "localhost"
718
+ ]);
719
+ function dt(e, t = !1) {
720
+ let r = e?.trim() || "127.0.0.1";
721
+ if (r.includes("://") || r.includes("/") || r.includes("\\") || !(n(r) || r === "localhost" || lt.test(r))) throw Error(`Invalid MCP HTTP host: ${e}`);
722
+ if (!t && !X(r)) throw Error(`Refusing unsafe MCP HTTP host ${r}; set CODEMEM_MCP_HTTP_UNSAFE_PUBLIC=1 to allow non-loopback binding`);
723
+ return r;
724
+ }
725
+ function X(e) {
726
+ return ut.has(Z(e));
727
+ }
728
+ function ft(e = process.env.CODEMEM_MCP_HTTP_UNSAFE_PUBLIC) {
729
+ return e === "1" || e?.toLowerCase() === "true" || e?.toLowerCase() === "yes";
730
+ }
731
+ function pt(e, t) {
732
+ let n = gt(e);
733
+ return !n || !X(n.host) ? !1 : n.port === null ? t === ct : n.port === t;
734
+ }
735
+ function mt(e, t) {
736
+ if (!e) return !0;
737
+ try {
738
+ let n = new URL(e), r = n.port ? Number(n.port) : n.protocol === "https:" ? 443 : 80;
739
+ return (n.protocol === "http:" || n.protocol === "https:") && n.username === "" && n.password === "" && n.pathname === "/" && n.search === "" && n.hash === "" && X(n.hostname) && r === t;
740
+ } catch {
741
+ return !1;
742
+ }
743
+ }
744
+ function ht(e) {
745
+ return e ? X(e.replace(/^::ffff:/, "")) : !1;
746
+ }
747
+ function Z(e) {
748
+ return e.replace(/^\[(.*)]$/, "$1").toLowerCase();
749
+ }
750
+ function gt(e) {
751
+ if (!e) return null;
752
+ if (e.startsWith("[")) {
753
+ let t = /^\[([^\]]+)]:(\d+)$/.exec(e);
754
+ if (t?.[1] && t[2]) return {
755
+ host: t[1],
756
+ port: Number(t[2])
757
+ };
758
+ let n = /^\[([^\]]+)]$/.exec(e);
759
+ return n?.[1] ? {
760
+ host: n[1],
761
+ port: null
762
+ } : null;
763
+ }
764
+ let t = e.lastIndexOf(":");
765
+ if (t < 0) return {
766
+ host: e,
767
+ port: null
768
+ };
769
+ let n = e.slice(0, t), r = Number(e.slice(t + 1));
770
+ return Number.isInteger(r) ? {
771
+ host: n,
772
+ port: r
773
+ } : null;
774
+ }
775
+ function Q(e) {
776
+ if (e === void 0 || e === "") return Y;
777
+ let t = typeof e == "number" ? e : Number(e);
778
+ if (!Number.isInteger(t) || t < 0 || t > 65535) throw Error(`Invalid MCP HTTP port: ${e}`);
779
+ return t;
780
+ }
781
+ async function _t(n = {}) {
782
+ let r = dt(n.host ?? process.env.CODEMEM_MCP_HTTP_HOST, n.allowUnsafePublic ?? ft()), s = Q(n.port ?? process.env.CODEMEM_MCP_HTTP_PORT), f = n.publicUrl ?? process.env.CODEMEM_MCP_HTTP_PUBLIC_URL, p = f ? L(f) : void 0, m = new i(n.dbPath ?? a()), h = ye(), g = be(), _ = n.oauthAccessTokenStore ?? xe(), v = qe(), y = Ke(), b = p !== void 0 || v !== void 0, x = te(n.auditEmitter ?? ie()), S = /* @__PURE__ */ new Set(), C = null, w = d();
783
+ w.disable("x-powered-by"), w.set("trust proxy", "loopback");
784
+ let T = t(w);
785
+ await new Promise((e, t) => {
786
+ T.once("error", t), T.listen({
787
+ host: r,
788
+ port: s
789
+ }, () => {
790
+ T.off("error", t), e();
791
+ });
792
+ });
793
+ let E = p?.href ?? wt(T, r), D = new URL(E), O = Tt(D, $(T)), k = new nt({
794
+ clientsStore: h,
795
+ codeStore: g,
796
+ tokenStore: _,
797
+ publicMcpUrl: E,
798
+ ...v ? { oidc: {
799
+ config: v,
800
+ pendingStore: y
801
+ } } : {}
802
+ }), ee = c(D);
803
+ w.use((e, t, n) => {
804
+ let r = $(T), i = Dt(e.path);
805
+ if (i === "/mcp") {
806
+ if (vt(e, r, p)) return n();
807
+ t.status(403).type("text/plain").send("Forbidden");
808
+ return;
809
+ }
810
+ if (Et(i)) {
811
+ if (bt(e, r, p)) return n();
812
+ t.status(403).type("text/plain").send("Forbidden");
813
+ return;
814
+ }
815
+ n();
816
+ }), w.use(Ot(x)), w.get("/oauth/callback", async (e, t) => {
817
+ let n = e.socket.remoteAddress ?? void 0;
818
+ if (!v) {
819
+ x(A("oidc_callback", {
820
+ outcome: "denied",
821
+ reason: "oidc_not_configured",
822
+ remoteAddress: n
823
+ })), t.status(400).json({
824
+ error: "temporarily_unavailable",
825
+ error_description: "OIDC is not configured"
826
+ });
827
+ return;
828
+ }
829
+ let r = await Ye(new URLSearchParams(e.query), y, v, E);
830
+ if ("status" in r) {
831
+ x(A("oidc_callback", {
832
+ outcome: "denied",
833
+ reason: r.body.error,
834
+ remoteAddress: n
835
+ })), t.status(r.status).json(r.body);
836
+ return;
837
+ }
838
+ let i = r.oauthParams.get("client_id") ?? void 0, a = g.issueCode({
839
+ clientId: r.oauthParams.get("client_id") ?? "",
840
+ redirectUri: r.oauthParams.get("redirect_uri") ?? "",
841
+ codeChallenge: r.oauthParams.get("code_challenge") ?? "",
842
+ scopes: Lt(r.oauthParams.get("scope")),
843
+ ...r.oauthParams.get("resource") ? { resource: r.oauthParams.get("resource") ?? void 0 } : {},
844
+ expiresAt: Date.now() + 300 * 1e3
845
+ });
846
+ if (!a) {
847
+ x(A("oidc_callback", {
848
+ outcome: "denied",
849
+ reason: "temporarily_unavailable",
850
+ clientId: i,
851
+ remoteAddress: n
852
+ })), t.status(400).json({
853
+ error: "temporarily_unavailable",
854
+ error_description: "Too many active authorization codes"
855
+ });
856
+ return;
857
+ }
858
+ let o = new URL(r.oauthParams.get("redirect_uri") ?? "");
859
+ o.searchParams.set("code", a);
860
+ let s = r.oauthParams.get("state");
861
+ s && o.searchParams.set("state", s), x(A("oidc_callback", {
862
+ outcome: "success",
863
+ reason: "code_issued",
864
+ clientId: i,
865
+ remoteAddress: n
866
+ })), t.redirect(302, o.href);
867
+ }), w.get("/.well-known/oauth-authorization-server", (e, t) => {
868
+ t.status(200).json(Ce({
869
+ mcpUrl: E,
870
+ clientsStore: h
871
+ }));
872
+ }), w.get("/.well-known/oauth-protected-resource/mcp", (e, t) => {
873
+ t.status(200).json(we(E));
874
+ }), w.use(l({
875
+ provider: k,
876
+ issuerUrl: O,
877
+ baseUrl: O,
878
+ resourceServerUrl: D,
879
+ resourceName: ae,
880
+ scopesSupported: j,
881
+ serviceDocumentationUrl: new URL(M),
882
+ clientRegistrationOptions: { clientSecretExpirySeconds: 0 }
883
+ }));
884
+ let ne = b ? o({
885
+ verifier: k,
886
+ resourceMetadataUrl: ee
887
+ }) : (e, t, n) => n(), re = b ? Ft(x, _) : (e, t, n) => n();
888
+ return w.post("/mcp", re, ne, async (t, n) => {
889
+ t.auth && x(A("bearer", {
890
+ outcome: "success",
891
+ clientId: t.auth.clientId,
892
+ remoteAddress: t.socket.remoteAddress ?? void 0
893
+ }));
894
+ let r = e(m), i = new u({ sessionIdGenerator: void 0 }), a = { mcpServer: r };
895
+ S.add(a);
896
+ try {
897
+ await r.connect(i), await i.handleRequest(t, n);
898
+ } finally {
899
+ S.delete(a), await r.close();
900
+ }
901
+ }), w.all("/mcp", (e, t) => {
902
+ t.setHeader("Allow", "POST"), t.status(405).type("text/plain").send("Method not allowed");
903
+ }), w.use((e, t) => {
904
+ t.status(404).type("text/plain").send("Not found");
905
+ }), {
906
+ server: T,
907
+ store: m,
908
+ url: `http://${Ct(r)}:${$(T)}/mcp`,
909
+ close: () => (C ??= (async () => {
910
+ await Promise.allSettled([...S].map(({ mcpServer: e }) => e.close())), await new Promise((e, t) => {
911
+ T.close((n) => {
912
+ if (!n || n.code === "ERR_SERVER_NOT_RUNNING") {
913
+ e();
914
+ return;
915
+ }
916
+ t(n);
917
+ }), T.closeAllConnections();
918
+ }), m.close();
919
+ })(), C)
920
+ };
921
+ }
922
+ function vt(e, t, n) {
923
+ return yt(e, t) ? !0 : n ? St(e.headers.host, n) && xt(e.headers.origin, n) : !1;
924
+ }
925
+ function yt(e, t) {
926
+ return ht(e.socket.remoteAddress) && pt(e.headers.host, t) && mt(e.headers.origin, t);
927
+ }
928
+ function bt(e, t, n) {
929
+ return yt(e, t) ? !0 : n ? St(e.headers.host, n) && xt(e.headers.origin, n) : !1;
930
+ }
931
+ function xt(e, t) {
932
+ if (!e) return !0;
933
+ try {
934
+ return new URL(e).origin === t.origin;
935
+ } catch {
936
+ return !1;
937
+ }
938
+ }
939
+ function St(e, t) {
940
+ let n = gt(e);
941
+ if (!n) return !1;
942
+ let r = t.port ? Number(t.port) : t.protocol === "https:" ? 443 : 80, i = n.port ?? r;
943
+ return Z(n.host) === Z(t.hostname) && i === r;
944
+ }
945
+ function $(e) {
946
+ let t = e.address();
947
+ return !t || typeof t == "string" ? Y : t.port;
948
+ }
949
+ function Ct(e) {
950
+ return n(e) === 6 ? `[${e}]` : e;
951
+ }
952
+ function wt(e, t) {
953
+ return `http://${Ct(t)}:${$(e)}/mcp`;
954
+ }
955
+ function Tt(e, t) {
956
+ return e.protocol === "https:" || X(e.hostname) && Z(e.hostname) !== "::1" ? new URL(e.origin) : new URL(`http://localhost:${t}/`);
957
+ }
958
+ function Et(e) {
959
+ return e === "/register" || e === "/authorize" || e === "/token" || e === "/revoke" || e === "/oauth/callback" || e === "/.well-known/oauth-authorization-server" || e === "/.well-known/oauth-protected-resource/mcp";
960
+ }
961
+ function Dt(e) {
962
+ return e.length > 1 ? e.replace(/\/+$/, "") : e;
963
+ }
964
+ function Ot(e) {
965
+ return (t, n, r) => {
966
+ let i = t.path;
967
+ if (!kt(i)) return r();
968
+ let a, o = n.json.bind(n);
969
+ n.json = ((e) => (a = e, o(e))), n.on("finish", () => {
970
+ if (i === "/oauth/callback") return;
971
+ let r = At(i, t);
972
+ if (!r) return;
973
+ let o = Mt(n, a), s = Pt(t, a);
974
+ e(A(r, {
975
+ outcome: o ? "denied" : "success",
976
+ ...o ? { reason: o } : {},
977
+ ...s ? { clientId: s } : {},
978
+ remoteAddress: t.socket.remoteAddress ?? void 0
979
+ }));
980
+ }), r();
981
+ };
982
+ }
983
+ function kt(e) {
984
+ return jt(e) !== null;
985
+ }
986
+ function At(e, t) {
987
+ return e === "/token" && t.body?.grant_type === "refresh_token" ? "refresh" : jt(e);
988
+ }
989
+ function jt(e) {
990
+ return e === "/register" ? "registration" : e === "/authorize" ? "authorize" : e === "/token" ? "token" : e === "/revoke" ? "revocation" : null;
991
+ }
992
+ function Mt(e, t) {
993
+ let n = Nt(t);
994
+ if (n) return n;
995
+ let r = e.getHeader("location");
996
+ if (typeof r == "string") try {
997
+ return new URL(r).searchParams.get("error") ?? void 0;
998
+ } catch {
999
+ return;
1000
+ }
1001
+ }
1002
+ function Nt(e) {
1003
+ if (typeof e == "object" && e && "error" in e && typeof e.error == "string") return e.error;
1004
+ }
1005
+ function Pt(e, t) {
1006
+ return typeof t == "object" && t && "client_id" in t && typeof t.client_id == "string" ? t.client_id : (typeof e.body?.client_id == "string" ? e.body.client_id : void 0) || (typeof e.query.client_id == "string" ? e.query.client_id : void 0);
1007
+ }
1008
+ function Ft(e, t) {
1009
+ return (n, r, i) => {
1010
+ let a = It(n.headers.authorization, t);
1011
+ a && e(A("bearer", {
1012
+ outcome: "denied",
1013
+ reason: a,
1014
+ remoteAddress: n.socket.remoteAddress ?? void 0
1015
+ })), i();
1016
+ };
1017
+ }
1018
+ function It(e, t) {
1019
+ if (!e) return "missing_authorization_header";
1020
+ let [n, r, i] = e.trim().split(/\s+/);
1021
+ if (!n || !r || i || n.toLowerCase() !== "bearer") return "malformed_authorization_header";
1022
+ let a = t.verifyToken(r);
1023
+ return a.ok ? null : a.reason;
1024
+ }
1025
+ function Lt(e) {
1026
+ return e?.split(/\s+/).map((e) => e.trim()).filter(Boolean) ?? [];
1027
+ }
1028
+ function Rt() {
1029
+ let e = process.argv[1];
1030
+ return e ? import.meta.url === r(e).href : !1;
1031
+ }
1032
+ async function zt() {
1033
+ let e = await _t();
1034
+ console.error(`codemem MCP HTTP server listening at ${e.url}`);
1035
+ let t = async () => {
1036
+ try {
1037
+ await e.close();
1038
+ } catch {}
1039
+ process.exit(0);
1040
+ };
1041
+ process.on("SIGINT", t), process.on("SIGTERM", t);
1042
+ }
1043
+ Rt() && zt().catch((e) => {
1044
+ console.error("codemem MCP HTTP server failed to start:", e), process.exit(1);
1045
+ });
1046
+ //#endregion
1047
+ export { st as DEFAULT_MCP_HTTP_HOST, Y as DEFAULT_MCP_HTTP_PORT, pt as isAllowedMcpHttpRequestHost, mt as isAllowedMcpHttpRequestOrigin, ht as isAllowedMcpHttpRequestRemoteAddress, X as isLoopbackHost, ft as isUnsafePublicBindAllowed, Q as parseMcpHttpPort, _t as startCodememMcpHttpServer, dt as validateMcpHttpHost };
1048
+
1049
+ //# sourceMappingURL=http.js.map