@softacus-software/elwis-mcp-core 0.1.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 (124) hide show
  1. package/README.md +120 -0
  2. package/dist/cjs/app-scope.js +81 -0
  3. package/dist/cjs/app-scope.js.map +1 -0
  4. package/dist/cjs/conformance/host.conformance.js +98 -0
  5. package/dist/cjs/conformance/host.conformance.js.map +1 -0
  6. package/dist/cjs/conformance/read-port.conformance.js +131 -0
  7. package/dist/cjs/conformance/read-port.conformance.js.map +1 -0
  8. package/dist/cjs/errors.js +74 -0
  9. package/dist/cjs/errors.js.map +1 -0
  10. package/dist/cjs/host/elwis-jwt-verifier.js +40 -0
  11. package/dist/cjs/host/elwis-jwt-verifier.js.map +1 -0
  12. package/dist/cjs/host/file-link-store.js +60 -0
  13. package/dist/cjs/host/file-link-store.js.map +1 -0
  14. package/dist/cjs/host/identity.js +3 -0
  15. package/dist/cjs/host/identity.js.map +1 -0
  16. package/dist/cjs/host/index.js +24 -0
  17. package/dist/cjs/host/index.js.map +1 -0
  18. package/dist/cjs/host/link-ticket.js +59 -0
  19. package/dist/cjs/host/link-ticket.js.map +1 -0
  20. package/dist/cjs/host/oidc-token.js +96 -0
  21. package/dist/cjs/host/oidc-token.js.map +1 -0
  22. package/dist/cjs/host/oidc-verifier.js +67 -0
  23. package/dist/cjs/host/oidc-verifier.js.map +1 -0
  24. package/dist/cjs/host/serve-http.js +282 -0
  25. package/dist/cjs/host/serve-http.js.map +1 -0
  26. package/dist/cjs/host/session-broker.js +84 -0
  27. package/dist/cjs/host/session-broker.js.map +1 -0
  28. package/dist/cjs/index.js +43 -0
  29. package/dist/cjs/index.js.map +1 -0
  30. package/dist/cjs/package.json +3 -0
  31. package/dist/cjs/plan/expand.js +297 -0
  32. package/dist/cjs/plan/expand.js.map +1 -0
  33. package/dist/cjs/plan/resolve-existing.js +58 -0
  34. package/dist/cjs/plan/resolve-existing.js.map +1 -0
  35. package/dist/cjs/plan/split.js +92 -0
  36. package/dist/cjs/plan/split.js.map +1 -0
  37. package/dist/cjs/plan/target-state.js +120 -0
  38. package/dist/cjs/plan/target-state.js.map +1 -0
  39. package/dist/cjs/ports/elwis-api.port.js +15 -0
  40. package/dist/cjs/ports/elwis-api.port.js.map +1 -0
  41. package/dist/cjs/resolve.js +89 -0
  42. package/dist/cjs/resolve.js.map +1 -0
  43. package/dist/esm/app-scope.d.ts +26 -0
  44. package/dist/esm/app-scope.d.ts.map +1 -0
  45. package/dist/esm/app-scope.js +76 -0
  46. package/dist/esm/app-scope.js.map +1 -0
  47. package/dist/esm/conformance/host.conformance.d.ts +3 -0
  48. package/dist/esm/conformance/host.conformance.d.ts.map +1 -0
  49. package/dist/esm/conformance/host.conformance.js +95 -0
  50. package/dist/esm/conformance/host.conformance.js.map +1 -0
  51. package/dist/esm/conformance/read-port.conformance.d.ts +24 -0
  52. package/dist/esm/conformance/read-port.conformance.d.ts.map +1 -0
  53. package/dist/esm/conformance/read-port.conformance.js +127 -0
  54. package/dist/esm/conformance/read-port.conformance.js.map +1 -0
  55. package/dist/esm/errors.d.ts +40 -0
  56. package/dist/esm/errors.d.ts.map +1 -0
  57. package/dist/esm/errors.js +63 -0
  58. package/dist/esm/errors.js.map +1 -0
  59. package/dist/esm/host/elwis-jwt-verifier.d.ts +9 -0
  60. package/dist/esm/host/elwis-jwt-verifier.d.ts.map +1 -0
  61. package/dist/esm/host/elwis-jwt-verifier.js +37 -0
  62. package/dist/esm/host/elwis-jwt-verifier.js.map +1 -0
  63. package/dist/esm/host/file-link-store.d.ts +13 -0
  64. package/dist/esm/host/file-link-store.d.ts.map +1 -0
  65. package/dist/esm/host/file-link-store.js +56 -0
  66. package/dist/esm/host/file-link-store.js.map +1 -0
  67. package/dist/esm/host/identity.d.ts +13 -0
  68. package/dist/esm/host/identity.d.ts.map +1 -0
  69. package/dist/esm/host/identity.js +2 -0
  70. package/dist/esm/host/identity.js.map +1 -0
  71. package/dist/esm/host/index.d.ts +15 -0
  72. package/dist/esm/host/index.d.ts.map +1 -0
  73. package/dist/esm/host/index.js +9 -0
  74. package/dist/esm/host/index.js.map +1 -0
  75. package/dist/esm/host/link-ticket.d.ts +17 -0
  76. package/dist/esm/host/link-ticket.d.ts.map +1 -0
  77. package/dist/esm/host/link-ticket.js +54 -0
  78. package/dist/esm/host/link-ticket.js.map +1 -0
  79. package/dist/esm/host/oidc-token.d.ts +20 -0
  80. package/dist/esm/host/oidc-token.d.ts.map +1 -0
  81. package/dist/esm/host/oidc-token.js +93 -0
  82. package/dist/esm/host/oidc-token.js.map +1 -0
  83. package/dist/esm/host/oidc-verifier.d.ts +14 -0
  84. package/dist/esm/host/oidc-verifier.d.ts.map +1 -0
  85. package/dist/esm/host/oidc-verifier.js +63 -0
  86. package/dist/esm/host/oidc-verifier.js.map +1 -0
  87. package/dist/esm/host/serve-http.d.ts +42 -0
  88. package/dist/esm/host/serve-http.d.ts.map +1 -0
  89. package/dist/esm/host/serve-http.js +278 -0
  90. package/dist/esm/host/serve-http.js.map +1 -0
  91. package/dist/esm/host/session-broker.d.ts +45 -0
  92. package/dist/esm/host/session-broker.d.ts.map +1 -0
  93. package/dist/esm/host/session-broker.js +77 -0
  94. package/dist/esm/host/session-broker.js.map +1 -0
  95. package/dist/esm/index.d.ts +18 -0
  96. package/dist/esm/index.d.ts.map +1 -0
  97. package/dist/esm/index.js +10 -0
  98. package/dist/esm/index.js.map +1 -0
  99. package/dist/esm/package.json +3 -0
  100. package/dist/esm/plan/expand.d.ts +37 -0
  101. package/dist/esm/plan/expand.d.ts.map +1 -0
  102. package/dist/esm/plan/expand.js +294 -0
  103. package/dist/esm/plan/expand.js.map +1 -0
  104. package/dist/esm/plan/resolve-existing.d.ts +16 -0
  105. package/dist/esm/plan/resolve-existing.d.ts.map +1 -0
  106. package/dist/esm/plan/resolve-existing.js +55 -0
  107. package/dist/esm/plan/resolve-existing.js.map +1 -0
  108. package/dist/esm/plan/split.d.ts +14 -0
  109. package/dist/esm/plan/split.d.ts.map +1 -0
  110. package/dist/esm/plan/split.js +88 -0
  111. package/dist/esm/plan/split.js.map +1 -0
  112. package/dist/esm/plan/target-state.d.ts +27 -0
  113. package/dist/esm/plan/target-state.d.ts.map +1 -0
  114. package/dist/esm/plan/target-state.js +114 -0
  115. package/dist/esm/plan/target-state.js.map +1 -0
  116. package/dist/esm/ports/elwis-api.port.d.ts +56 -0
  117. package/dist/esm/ports/elwis-api.port.d.ts.map +1 -0
  118. package/dist/esm/ports/elwis-api.port.js +12 -0
  119. package/dist/esm/ports/elwis-api.port.js.map +1 -0
  120. package/dist/esm/resolve.d.ts +23 -0
  121. package/dist/esm/resolve.d.ts.map +1 -0
  122. package/dist/esm/resolve.js +79 -0
  123. package/dist/esm/resolve.js.map +1 -0
  124. package/package.json +55 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/host/identity.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RunHostConformance = exports.FileLinkStore = exports.LinkKey = exports.AccountNotLinkedError = exports.MemoryLinkStore = exports.ElwisSessionBroker = exports.OidcVerifier = exports.VerifyOidcToken = exports.ElwisJwtVerifier = exports.ServeMcpHttp = exports.ReadLinkTicket = exports.CreateLinkTicket = void 0;
4
+ var link_ticket_js_1 = require("./link-ticket.js");
5
+ Object.defineProperty(exports, "CreateLinkTicket", { enumerable: true, get: function () { return link_ticket_js_1.CreateLinkTicket; } });
6
+ Object.defineProperty(exports, "ReadLinkTicket", { enumerable: true, get: function () { return link_ticket_js_1.ReadLinkTicket; } });
7
+ var serve_http_js_1 = require("./serve-http.js");
8
+ Object.defineProperty(exports, "ServeMcpHttp", { enumerable: true, get: function () { return serve_http_js_1.ServeMcpHttp; } });
9
+ var elwis_jwt_verifier_js_1 = require("./elwis-jwt-verifier.js");
10
+ Object.defineProperty(exports, "ElwisJwtVerifier", { enumerable: true, get: function () { return elwis_jwt_verifier_js_1.ElwisJwtVerifier; } });
11
+ var oidc_token_js_1 = require("./oidc-token.js");
12
+ Object.defineProperty(exports, "VerifyOidcToken", { enumerable: true, get: function () { return oidc_token_js_1.VerifyOidcToken; } });
13
+ var oidc_verifier_js_1 = require("./oidc-verifier.js");
14
+ Object.defineProperty(exports, "OidcVerifier", { enumerable: true, get: function () { return oidc_verifier_js_1.OidcVerifier; } });
15
+ var session_broker_js_1 = require("./session-broker.js");
16
+ Object.defineProperty(exports, "ElwisSessionBroker", { enumerable: true, get: function () { return session_broker_js_1.ElwisSessionBroker; } });
17
+ Object.defineProperty(exports, "MemoryLinkStore", { enumerable: true, get: function () { return session_broker_js_1.MemoryLinkStore; } });
18
+ Object.defineProperty(exports, "AccountNotLinkedError", { enumerable: true, get: function () { return session_broker_js_1.AccountNotLinkedError; } });
19
+ Object.defineProperty(exports, "LinkKey", { enumerable: true, get: function () { return session_broker_js_1.LinkKey; } });
20
+ var file_link_store_js_1 = require("./file-link-store.js");
21
+ Object.defineProperty(exports, "FileLinkStore", { enumerable: true, get: function () { return file_link_store_js_1.FileLinkStore; } });
22
+ var host_conformance_js_1 = require("../conformance/host.conformance.js");
23
+ Object.defineProperty(exports, "RunHostConformance", { enumerable: true, get: function () { return host_conformance_js_1.RunHostConformance; } });
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/host/index.ts"],"names":[],"mappings":";;;AAEA,mDAAoE;AAA3D,kHAAA,gBAAgB,OAAA;AAAE,gHAAA,cAAc,OAAA;AAEzC,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AACrB,iEAA2D;AAAlD,yHAAA,gBAAgB,OAAA;AACzB,iDAAkD;AAAzC,gHAAA,eAAe,OAAA;AAExB,uDAAkD;AAAzC,gHAAA,YAAY,OAAA;AACrB,yDAA0G;AAAjG,uHAAA,kBAAkB,OAAA;AAAE,oHAAA,eAAe,OAAA;AAAE,0HAAA,qBAAqB,OAAA;AAAE,4GAAA,OAAO,OAAA;AAC5E,2DAAqD;AAA5C,mHAAA,aAAa,OAAA;AAKtB,0EAAwE;AAA/D,yHAAA,kBAAkB,OAAA"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_LINK_TICKET_TTL_SECONDS = void 0;
4
+ exports.CreateLinkTicket = CreateLinkTicket;
5
+ exports.ReadLinkTicket = ReadLinkTicket;
6
+ const node_crypto_1 = require("node:crypto");
7
+ exports.DEFAULT_LINK_TICKET_TTL_SECONDS = 600;
8
+ function Sign(body, secret) {
9
+ return (0, node_crypto_1.createHmac)('sha256', secret).update(body).digest('base64url');
10
+ }
11
+ function Matches(a, b) {
12
+ const left = Buffer.from(a);
13
+ const right = Buffer.from(b);
14
+ return left.length === right.length && (0, node_crypto_1.timingSafeEqual)(left, right);
15
+ }
16
+ function CreateLinkTicket(claims, options) {
17
+ const now = options.now ?? Math.floor(Date.now() / 1000);
18
+ const body = {
19
+ iss: claims.iss,
20
+ sub: claims.sub,
21
+ ...(claims.email ? { email: claims.email } : {}),
22
+ ...(claims.resource ? { resource: claims.resource } : {}),
23
+ exp: now + (options.ttlSeconds ?? exports.DEFAULT_LINK_TICKET_TTL_SECONDS),
24
+ };
25
+ const encoded = Buffer.from(JSON.stringify(body)).toString('base64url');
26
+ return `${encoded}.${Sign(encoded, options.secret)}`;
27
+ }
28
+ function ReadLinkTicket(ticket, options) {
29
+ const parts = ticket.split('.');
30
+ const [encoded, signature] = parts;
31
+ if (parts.length !== 2 || !encoded || !signature) {
32
+ throw new Error('the link ticket is malformed');
33
+ }
34
+ if (!Matches(signature, Sign(encoded, options.secret))) {
35
+ throw new Error('the link ticket signature does not verify');
36
+ }
37
+ let body;
38
+ try {
39
+ body = JSON.parse(Buffer.from(encoded, 'base64url').toString('utf8'));
40
+ }
41
+ catch {
42
+ throw new Error('the link ticket payload is not valid JSON');
43
+ }
44
+ const parsed = body;
45
+ if (typeof parsed.iss !== 'string' || typeof parsed.sub !== 'string' || typeof parsed.exp !== 'number') {
46
+ throw new Error('the link ticket payload is incomplete');
47
+ }
48
+ if (parsed.exp <= (options.now ?? Math.floor(Date.now() / 1000))) {
49
+ throw new Error('the link ticket has expired');
50
+ }
51
+ return {
52
+ iss: parsed.iss,
53
+ sub: parsed.sub,
54
+ ...(typeof parsed.email === 'string' ? { email: parsed.email } : {}),
55
+ ...(typeof parsed.resource === 'string' ? { resource: parsed.resource } : {}),
56
+ exp: parsed.exp,
57
+ };
58
+ }
59
+ //# sourceMappingURL=link-ticket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-ticket.js","sourceRoot":"","sources":["../../../src/host/link-ticket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VerifyOidcToken = VerifyOidcToken;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const DEFAULT_CLOCK_SKEW_SECONDS = 60;
6
+ const ALGORITHMS = {
7
+ RS256: { importParams: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, verifyParams: { name: 'RSASSA-PKCS1-v1_5' } },
8
+ RS384: { importParams: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-384' }, verifyParams: { name: 'RSASSA-PKCS1-v1_5' } },
9
+ RS512: { importParams: { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-512' }, verifyParams: { name: 'RSASSA-PKCS1-v1_5' } },
10
+ ES256: { importParams: { name: 'ECDSA', namedCurve: 'P-256' }, verifyParams: { name: 'ECDSA', hash: 'SHA-256' } },
11
+ ES384: { importParams: { name: 'ECDSA', namedCurve: 'P-384' }, verifyParams: { name: 'ECDSA', hash: 'SHA-384' } },
12
+ ES512: { importParams: { name: 'ECDSA', namedCurve: 'P-521' }, verifyParams: { name: 'ECDSA', hash: 'SHA-512' } },
13
+ };
14
+ function DecodeSegment(segment, what) {
15
+ let parsed;
16
+ try {
17
+ parsed = JSON.parse(Buffer.from(segment, 'base64url').toString('utf8'));
18
+ }
19
+ catch {
20
+ throw new Error(`the token ${what} is not valid JSON`);
21
+ }
22
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
23
+ throw new Error(`the token ${what} is not an object`);
24
+ }
25
+ return parsed;
26
+ }
27
+ function Audiences(claim) {
28
+ if (typeof claim === 'string')
29
+ return [claim];
30
+ if (Array.isArray(claim))
31
+ return claim.filter((entry) => typeof entry === 'string');
32
+ return [];
33
+ }
34
+ function SameResource(a, b) {
35
+ return a.replace(/\/+$/, '') === b.replace(/\/+$/, '');
36
+ }
37
+ async function VerifyOidcToken(token, options) {
38
+ const parts = token.split('.');
39
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
40
+ if (parts.length !== 3 || !encodedHeader || !encodedPayload || encodedSignature === undefined) {
41
+ throw new Error('the bearer value is not a JWS compact serialization');
42
+ }
43
+ const header = DecodeSegment(encodedHeader, 'header');
44
+ const algorithm = typeof header.alg === 'string' ? ALGORITHMS[header.alg] : undefined;
45
+ if (!algorithm) {
46
+ throw new Error(`unsupported token signing algorithm: ${String(header.alg)}`);
47
+ }
48
+ const kid = typeof header.kid === 'string' ? header.kid : null;
49
+ const candidates = options.jwks.keys.filter(key => kid === null || key.kid === kid);
50
+ if (candidates.length === 0) {
51
+ throw new Error(`no key in the issuer key set matches kid ${kid ?? '(absent)'}`);
52
+ }
53
+ const signed = Buffer.from(`${encodedHeader}.${encodedPayload}`, 'utf8');
54
+ const signature = Buffer.from(encodedSignature, 'base64url');
55
+ let verified = false;
56
+ for (const jwk of candidates) {
57
+ let key;
58
+ try {
59
+ key = await node_crypto_1.webcrypto.subtle.importKey('jwk', jwk, algorithm.importParams, false, ['verify']);
60
+ }
61
+ catch {
62
+ continue;
63
+ }
64
+ if (await node_crypto_1.webcrypto.subtle.verify(algorithm.verifyParams, key, signature, signed)) {
65
+ verified = true;
66
+ break;
67
+ }
68
+ }
69
+ if (!verified) {
70
+ throw new Error('the token signature does not verify against the issuer key set');
71
+ }
72
+ const payload = DecodeSegment(encodedPayload, 'payload');
73
+ if (payload.iss !== options.issuer) {
74
+ throw new Error(`the token issuer ${String(payload.iss)} is not the configured issuer`);
75
+ }
76
+ const audiences = Audiences(payload.aud);
77
+ if (!audiences.some(entry => SameResource(entry, options.resource))) {
78
+ throw new Error(`the token audience does not include this resource (${options.resource})`);
79
+ }
80
+ const now = options.now ?? Math.floor(Date.now() / 1000);
81
+ const skew = options.clockSkewSeconds ?? DEFAULT_CLOCK_SKEW_SECONDS;
82
+ if (typeof payload.exp !== 'number') {
83
+ throw new Error('the token has no exp claim');
84
+ }
85
+ if (payload.exp <= now) {
86
+ throw new Error('the token has expired');
87
+ }
88
+ if (typeof payload.nbf === 'number' && payload.nbf - skew > now) {
89
+ throw new Error('the token is not valid yet');
90
+ }
91
+ if (typeof payload.sub !== 'string' || payload.sub.length === 0) {
92
+ throw new Error('the token has no sub claim');
93
+ }
94
+ return { ...payload, sub: payload.sub, iss: options.issuer, aud: audiences, exp: payload.exp };
95
+ }
96
+ //# sourceMappingURL=oidc-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-token.js","sourceRoot":"","sources":["../../../src/host/oidc-token.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_KEY_CACHE_SECONDS = void 0;
4
+ exports.OidcVerifier = OidcVerifier;
5
+ const oidc_token_js_1 = require("./oidc-token.js");
6
+ exports.DEFAULT_KEY_CACHE_SECONDS = 600;
7
+ const DISCOVERY_SUFFIX = '/.well-known/openid-configuration';
8
+ async function DefaultFetchJson(url) {
9
+ const res = await fetch(url);
10
+ if (!res.ok)
11
+ throw new Error(`${url} answered ${res.status}`);
12
+ return res.json();
13
+ }
14
+ function KeyIds(jwks) {
15
+ return new Set(jwks.keys.map(key => (typeof key.kid === 'string' ? key.kid : '')));
16
+ }
17
+ function TokenKeyId(token) {
18
+ const header = token.split('.')[0];
19
+ if (!header)
20
+ return null;
21
+ try {
22
+ const parsed = JSON.parse(Buffer.from(header, 'base64url').toString('utf8'));
23
+ return typeof parsed.kid === 'string' ? parsed.kid : null;
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ function OidcVerifier(options) {
30
+ const fetchJson = options.fetchJson ?? DefaultFetchJson;
31
+ const now = options.now ?? Date.now;
32
+ const cacheMs = (options.keyCacheSeconds ?? exports.DEFAULT_KEY_CACHE_SECONDS) * 1000;
33
+ let jwksUri = null;
34
+ let cached = null;
35
+ let cachedAt = 0;
36
+ async function KeySet(refresh) {
37
+ if (cached && !refresh && now() - cachedAt < cacheMs)
38
+ return cached;
39
+ if (jwksUri === null) {
40
+ const discovery = await fetchJson(`${options.issuer.replace(/\/+$/, '')}${DISCOVERY_SUFFIX}`);
41
+ if (typeof discovery.jwks_uri !== 'string') {
42
+ throw new Error(`the issuer ${options.issuer} published no jwks_uri`);
43
+ }
44
+ jwksUri = discovery.jwks_uri;
45
+ }
46
+ cached = await fetchJson(jwksUri);
47
+ cachedAt = now();
48
+ return cached;
49
+ }
50
+ return {
51
+ async verify(token, resource) {
52
+ let jwks = await KeySet(false);
53
+ const kid = TokenKeyId(token);
54
+ if (kid !== null && !KeyIds(jwks).has(kid)) {
55
+ jwks = await KeySet(true);
56
+ }
57
+ const claims = await (0, oidc_token_js_1.VerifyOidcToken)(token, {
58
+ issuer: options.issuer,
59
+ resource,
60
+ jwks,
61
+ clockSkewSeconds: options.clockSkewSeconds,
62
+ });
63
+ return options.broker.resolve(claims);
64
+ },
65
+ };
66
+ }
67
+ //# sourceMappingURL=oidc-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-verifier.js","sourceRoot":"","sources":["../../../src/host/oidc-verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,282 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_MAX_CONCURRENT_SESSIONS = exports.DEFAULT_MAX_CONCURRENT_VERIFICATIONS = void 0;
4
+ exports.ServeMcpHttp = ServeMcpHttp;
5
+ const node_http_1 = require("node:http");
6
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
7
+ const link_ticket_js_1 = require("./link-ticket.js");
8
+ exports.DEFAULT_MAX_CONCURRENT_VERIFICATIONS = 50;
9
+ exports.DEFAULT_MAX_CONCURRENT_SESSIONS = 200;
10
+ const METADATA_PATH = '/.well-known/oauth-protected-resource';
11
+ function BearerToken(req) {
12
+ const header = req.headers.authorization;
13
+ if (!header)
14
+ return null;
15
+ const match = /^Bearer\s+(.+)$/i.exec(header.trim());
16
+ return match?.[1] ?? null;
17
+ }
18
+ function MetadataUrl(resource) {
19
+ const url = new URL(resource);
20
+ const isHttp = url.protocol === 'http:' || url.protocol === 'https:';
21
+ if (!isHttp || url.username || url.password || url.search || url.hash) {
22
+ throw new Error('resource must be an absolute http(s) URL without userinfo, query or fragment');
23
+ }
24
+ const suffix = url.pathname === '/' ? '' : url.pathname;
25
+ return `${url.origin}${METADATA_PATH}${suffix}`;
26
+ }
27
+ function ValidatedCap(name, value, defaultValue) {
28
+ if (value === undefined)
29
+ return defaultValue;
30
+ if (!Number.isInteger(value) || value < 1) {
31
+ throw new Error(`${name} must be a finite integer of at least 1, got: ${value}`);
32
+ }
33
+ return value;
34
+ }
35
+ function HeaderSafeValue(value) {
36
+ return value.replace(/[^\x20-\x7e]/g, '').replace(/"/g, "'");
37
+ }
38
+ const MAX_LINK_BODY_BYTES = 8192;
39
+ function Html(value) {
40
+ return value.replace(/[&<>"]/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]));
41
+ }
42
+ function LinkPage(res, status, heading, detail, form = '') {
43
+ res.writeHead(status, {
44
+ 'content-type': 'text/html; charset=utf-8',
45
+ 'cache-control': 'no-store',
46
+ 'x-frame-options': 'DENY',
47
+ 'content-security-policy': "frame-ancestors 'none'",
48
+ });
49
+ res.end(`<!doctype html><meta charset=utf-8><title>${Html(heading)}</title>`
50
+ + `<body style="font:16px/1.5 system-ui,sans-serif;max-width:34rem;margin:15vh auto;padding:0 1.5rem">`
51
+ + `<h1 style="font-size:1.4rem;margin:0 0 .5rem">${Html(heading)}</h1>`
52
+ + `<p style="color:#555;margin:0">${Html(detail)}</p>${form}`);
53
+ }
54
+ function ConfirmLinkPage(res, path, ticket, claims) {
55
+ const who = claims.email ?? claims.sub;
56
+ const form = `<form method="post" action="${Html(path)}" style="margin-top:1.5rem">`
57
+ + `<input type="hidden" name="ticket" value="${Html(ticket)}">`
58
+ + `<button type="submit" style="font:inherit;padding:.6rem 1.2rem;border-radius:8px;border:0;background:#1f4fd1;color:#fff;cursor:pointer">Link my ELWIS account</button>`
59
+ + `</form>`;
60
+ LinkPage(res, 200, 'Link your ELWIS account', `The assistant signed in as ${who} asks to work in ELWIS with your current ELWIS session. Continue only if ${who} is you.`, form);
61
+ }
62
+ async function ReadFormTicket(req) {
63
+ let size = 0;
64
+ const chunks = [];
65
+ for await (const chunk of req) {
66
+ size += chunk.length;
67
+ if (size > MAX_LINK_BODY_BYTES)
68
+ throw new Error('the link request is too large');
69
+ chunks.push(chunk);
70
+ }
71
+ return new URLSearchParams(Buffer.concat(chunks).toString('utf8')).get('ticket');
72
+ }
73
+ function LinkUrlOf(error) {
74
+ const candidate = error?.linkUrl;
75
+ return typeof candidate === 'string' && candidate.length > 0 ? candidate : null;
76
+ }
77
+ function Challenge(res, metadataUrl, description, linkUrl) {
78
+ const safeDescription = HeaderSafeValue(description);
79
+ const safeLink = linkUrl ? HeaderSafeValue(linkUrl) : null;
80
+ res.writeHead(401, {
81
+ 'www-authenticate': `Bearer resource_metadata="${metadataUrl}", error="invalid_token", error_description="${safeDescription}"`
82
+ + (safeLink ? `, link_url="${safeLink}"` : ''),
83
+ 'content-type': 'application/json',
84
+ });
85
+ res.end(JSON.stringify({ error: 'invalid_token', error_description: safeDescription, ...(safeLink ? { link_url: safeLink } : {}) }));
86
+ }
87
+ function ResolveEndpoints(options) {
88
+ if (options.endpoints?.length) {
89
+ if (options.resource !== undefined) {
90
+ throw new Error('pass either resource or endpoints, not both');
91
+ }
92
+ return options.endpoints;
93
+ }
94
+ if (options.resource === undefined) {
95
+ throw new Error('one of resource or endpoints is required');
96
+ }
97
+ return [{ path: options.path ?? '/mcp', resource: options.resource }];
98
+ }
99
+ async function ServeMcpHttp(options) {
100
+ const host = options.host ?? '127.0.0.1';
101
+ const endpoints = ResolveEndpoints(options).map(e => ({ ...e, metadataUrl: MetadataUrl(e.resource) }));
102
+ const byPath = new Map(endpoints.map(e => [e.path, e]));
103
+ const byMetadataPath = new Map(endpoints.map(e => [new URL(e.metadataUrl).pathname, e]));
104
+ const firstEndpoint = endpoints[0];
105
+ const maxConcurrentVerifications = ValidatedCap('maxConcurrentVerifications', options.maxConcurrentVerifications, exports.DEFAULT_MAX_CONCURRENT_VERIFICATIONS);
106
+ const maxConcurrentSessions = ValidatedCap('maxConcurrentSessions', options.maxConcurrentSessions, exports.DEFAULT_MAX_CONCURRENT_SESSIONS);
107
+ let inFlightVerifications = 0;
108
+ let liveSessions = 0;
109
+ const usedTickets = new Map();
110
+ const server = (0, node_http_1.createServer)(async (req, res) => {
111
+ try {
112
+ const requestPath = req.url?.split('?')[0] ?? '';
113
+ const metadataFor = requestPath === METADATA_PATH ? firstEndpoint : byMetadataPath.get(requestPath);
114
+ if (req.method === 'GET' && metadataFor) {
115
+ res.writeHead(200, { 'content-type': 'application/json' });
116
+ res.end(JSON.stringify({
117
+ resource: metadataFor.resource,
118
+ authorization_servers: options.authorizationServers,
119
+ bearer_methods_supported: ['header'],
120
+ }));
121
+ return;
122
+ }
123
+ const linkPath = options.link?.path ?? '/link';
124
+ if (options.link && requestPath === linkPath) {
125
+ if (req.method !== 'GET' && req.method !== 'POST') {
126
+ res.writeHead(405, { allow: 'GET, POST' });
127
+ res.end();
128
+ return;
129
+ }
130
+ let ticket;
131
+ let claims;
132
+ try {
133
+ ticket = req.method === 'POST' ? await ReadFormTicket(req) : new URL(req.url ?? '/', 'http://host').searchParams.get('ticket');
134
+ if (!ticket)
135
+ throw new Error('a link ticket is required');
136
+ claims = (0, link_ticket_js_1.ReadLinkTicket)(ticket, { secret: options.link.secret });
137
+ if (usedTickets.has(ticket))
138
+ throw new Error('this link was already used; ask the assistant for a new one');
139
+ }
140
+ catch (e) {
141
+ LinkPage(res, 400, 'This link cannot be used', e instanceof Error ? e.message : 'the link ticket was rejected');
142
+ return;
143
+ }
144
+ if (req.method === 'GET') {
145
+ ConfirmLinkPage(res, linkPath, ticket, claims);
146
+ return;
147
+ }
148
+ let outcome;
149
+ try {
150
+ outcome = await options.link.complete(claims, { headers: req.headers });
151
+ }
152
+ catch (e) {
153
+ LinkPage(res, 502, 'ELWIS could not complete the sign-in', e instanceof Error ? e.message : 'unknown failure');
154
+ return;
155
+ }
156
+ if (outcome.status === 'needs-sign-in') {
157
+ let target;
158
+ try {
159
+ target = new URL(outcome.signInUrl);
160
+ }
161
+ catch {
162
+ LinkPage(res, 500, 'The sign-in address is not usable', 'the configured sign-in url is not an absolute url');
163
+ return;
164
+ }
165
+ if (target.protocol !== 'http:' && target.protocol !== 'https:') {
166
+ LinkPage(res, 500, 'The sign-in address is not usable', 'the configured sign-in url is not http or https');
167
+ return;
168
+ }
169
+ res.writeHead(302, { location: target.toString(), 'cache-control': 'no-store' });
170
+ res.end();
171
+ return;
172
+ }
173
+ const nowSeconds = Math.floor(Date.now() / 1000);
174
+ for (const [used, exp] of usedTickets)
175
+ if (exp <= nowSeconds)
176
+ usedTickets.delete(used);
177
+ usedTickets.set(ticket, claims.exp);
178
+ LinkPage(res, 200, 'Account linked', 'You can close this tab and go back to your assistant.');
179
+ return;
180
+ }
181
+ const endpoint = byPath.get(requestPath);
182
+ if (!endpoint) {
183
+ res.writeHead(404, { 'content-type': 'application/json' });
184
+ res.end(JSON.stringify({ error: 'not_found' }));
185
+ return;
186
+ }
187
+ if (req.method === 'GET') {
188
+ res.writeHead(405, { 'content-type': 'application/json', allow: 'POST' });
189
+ res.end(JSON.stringify({ error: 'method_not_allowed', error_description: 'GET is not supported; this server does not send server-initiated messages' }));
190
+ return;
191
+ }
192
+ const token = BearerToken(req);
193
+ if (!token) {
194
+ Challenge(res, endpoint.metadataUrl, 'a bearer token is required');
195
+ return;
196
+ }
197
+ if (inFlightVerifications >= maxConcurrentVerifications) {
198
+ res.writeHead(503, { 'content-type': 'application/json', 'retry-after': '1' });
199
+ res.end(JSON.stringify({ error: 'too_many_requests', error_description: 'too many verifications in flight; try again shortly' }));
200
+ return;
201
+ }
202
+ let identity;
203
+ inFlightVerifications++;
204
+ try {
205
+ identity = await options.verifier.verify(token, endpoint.resource);
206
+ }
207
+ catch (e) {
208
+ const linkUrl = LinkUrlOf(e);
209
+ Challenge(res, endpoint.metadataUrl, linkUrl ? 'this account is not linked to ELWIS yet' : 'the token was rejected', linkUrl);
210
+ return;
211
+ }
212
+ finally {
213
+ inFlightVerifications--;
214
+ }
215
+ if (liveSessions >= maxConcurrentSessions) {
216
+ res.writeHead(503, { 'content-type': 'application/json', 'retry-after': '1' });
217
+ res.end(JSON.stringify({ error: 'too_many_requests', error_description: 'too many sessions in flight; try again shortly' }));
218
+ return;
219
+ }
220
+ liveSessions++;
221
+ let sessionReleased = false;
222
+ const releaseSession = () => {
223
+ if (sessionReleased)
224
+ return;
225
+ sessionReleased = true;
226
+ liveSessions--;
227
+ };
228
+ try {
229
+ const mcp = options.factory(identity);
230
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
231
+ res.on('close', () => {
232
+ transport.close().catch(() => { });
233
+ mcp.close().catch(() => { });
234
+ releaseSession();
235
+ });
236
+ await mcp.connect(transport);
237
+ await transport.handleRequest(req, res);
238
+ }
239
+ catch (e) {
240
+ releaseSession();
241
+ throw e;
242
+ }
243
+ }
244
+ catch {
245
+ if (!res.headersSent) {
246
+ res.writeHead(500, { 'content-type': 'application/json' });
247
+ res.end(JSON.stringify({ error: 'internal_error' }));
248
+ }
249
+ else {
250
+ res.end();
251
+ }
252
+ }
253
+ });
254
+ await new Promise((resolve, reject) => {
255
+ const onListenError = (err) => reject(err);
256
+ server.once('error', onListenError);
257
+ server.listen(options.port ?? 0, host, () => {
258
+ server.removeListener('error', onListenError);
259
+ resolve();
260
+ });
261
+ });
262
+ const address = server.address();
263
+ const port = typeof address === 'object' && address ? address.port : 0;
264
+ return {
265
+ port,
266
+ close: () => new Promise((resolve, reject) => {
267
+ server.closeAllConnections();
268
+ server.close(err => {
269
+ if (!err) {
270
+ resolve();
271
+ return;
272
+ }
273
+ if (err.code === 'ERR_SERVER_NOT_RUNNING') {
274
+ resolve();
275
+ return;
276
+ }
277
+ reject(err);
278
+ });
279
+ }),
280
+ };
281
+ }
282
+ //# sourceMappingURL=serve-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-http.js","sourceRoot":"","sources":["../../../src/host/serve-http.ts"],"names":[],"mappings":"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"}