@kya-os/mcp 1.2.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 (182) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +21 -0
  3. package/README.md +135 -0
  4. package/dist/auth/handshake.d.ts +119 -0
  5. package/dist/auth/handshake.d.ts.map +1 -0
  6. package/dist/auth/handshake.js +267 -0
  7. package/dist/auth/handshake.js.map +1 -0
  8. package/dist/auth/index.d.ts +3 -0
  9. package/dist/auth/index.d.ts.map +1 -0
  10. package/dist/auth/index.js +2 -0
  11. package/dist/auth/index.js.map +1 -0
  12. package/dist/auth/types.d.ts +31 -0
  13. package/dist/auth/types.d.ts.map +1 -0
  14. package/dist/auth/types.js +7 -0
  15. package/dist/auth/types.js.map +1 -0
  16. package/dist/delegation/audience-validator.d.ts +9 -0
  17. package/dist/delegation/audience-validator.d.ts.map +1 -0
  18. package/dist/delegation/audience-validator.js +17 -0
  19. package/dist/delegation/audience-validator.js.map +1 -0
  20. package/dist/delegation/bitstring.d.ts +37 -0
  21. package/dist/delegation/bitstring.d.ts.map +1 -0
  22. package/dist/delegation/bitstring.js +117 -0
  23. package/dist/delegation/bitstring.js.map +1 -0
  24. package/dist/delegation/cascading-revocation.d.ts +45 -0
  25. package/dist/delegation/cascading-revocation.d.ts.map +1 -0
  26. package/dist/delegation/cascading-revocation.js +150 -0
  27. package/dist/delegation/cascading-revocation.js.map +1 -0
  28. package/dist/delegation/delegation-graph.d.ts +49 -0
  29. package/dist/delegation/delegation-graph.d.ts.map +1 -0
  30. package/dist/delegation/delegation-graph.js +99 -0
  31. package/dist/delegation/delegation-graph.js.map +1 -0
  32. package/dist/delegation/did-key-resolver.d.ts +64 -0
  33. package/dist/delegation/did-key-resolver.d.ts.map +1 -0
  34. package/dist/delegation/did-key-resolver.js +157 -0
  35. package/dist/delegation/did-key-resolver.js.map +1 -0
  36. package/dist/delegation/did-web-resolver.d.ts +83 -0
  37. package/dist/delegation/did-web-resolver.d.ts.map +1 -0
  38. package/dist/delegation/did-web-resolver.js +218 -0
  39. package/dist/delegation/did-web-resolver.js.map +1 -0
  40. package/dist/delegation/index.d.ts +21 -0
  41. package/dist/delegation/index.d.ts.map +1 -0
  42. package/dist/delegation/index.js +21 -0
  43. package/dist/delegation/index.js.map +1 -0
  44. package/dist/delegation/outbound-headers.d.ts +79 -0
  45. package/dist/delegation/outbound-headers.d.ts.map +1 -0
  46. package/dist/delegation/outbound-headers.js +138 -0
  47. package/dist/delegation/outbound-headers.js.map +1 -0
  48. package/dist/delegation/outbound-proof.d.ts +43 -0
  49. package/dist/delegation/outbound-proof.d.ts.map +1 -0
  50. package/dist/delegation/outbound-proof.js +52 -0
  51. package/dist/delegation/outbound-proof.js.map +1 -0
  52. package/dist/delegation/statuslist-manager.d.ts +47 -0
  53. package/dist/delegation/statuslist-manager.d.ts.map +1 -0
  54. package/dist/delegation/statuslist-manager.js +139 -0
  55. package/dist/delegation/statuslist-manager.js.map +1 -0
  56. package/dist/delegation/storage/memory-graph-storage.d.ts +70 -0
  57. package/dist/delegation/storage/memory-graph-storage.d.ts.map +1 -0
  58. package/dist/delegation/storage/memory-graph-storage.js +145 -0
  59. package/dist/delegation/storage/memory-graph-storage.js.map +1 -0
  60. package/dist/delegation/storage/memory-statuslist-storage.d.ts +19 -0
  61. package/dist/delegation/storage/memory-statuslist-storage.d.ts.map +1 -0
  62. package/dist/delegation/storage/memory-statuslist-storage.js +33 -0
  63. package/dist/delegation/storage/memory-statuslist-storage.js.map +1 -0
  64. package/dist/delegation/utils.d.ts +49 -0
  65. package/dist/delegation/utils.d.ts.map +1 -0
  66. package/dist/delegation/utils.js +131 -0
  67. package/dist/delegation/utils.js.map +1 -0
  68. package/dist/delegation/vc-issuer.d.ts +56 -0
  69. package/dist/delegation/vc-issuer.d.ts.map +1 -0
  70. package/dist/delegation/vc-issuer.js +80 -0
  71. package/dist/delegation/vc-issuer.js.map +1 -0
  72. package/dist/delegation/vc-verifier.d.ts +112 -0
  73. package/dist/delegation/vc-verifier.d.ts.map +1 -0
  74. package/dist/delegation/vc-verifier.js +280 -0
  75. package/dist/delegation/vc-verifier.js.map +1 -0
  76. package/dist/errors.d.ts +42 -0
  77. package/dist/errors.d.ts.map +1 -0
  78. package/dist/errors.js +45 -0
  79. package/dist/errors.js.map +1 -0
  80. package/dist/index.d.ts +47 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +56 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/logging/index.d.ts +2 -0
  85. package/dist/logging/index.d.ts.map +1 -0
  86. package/dist/logging/index.js +2 -0
  87. package/dist/logging/index.js.map +1 -0
  88. package/dist/logging/logger.d.ts +23 -0
  89. package/dist/logging/logger.d.ts.map +1 -0
  90. package/dist/logging/logger.js +82 -0
  91. package/dist/logging/logger.js.map +1 -0
  92. package/dist/middleware/index.d.ts +12 -0
  93. package/dist/middleware/index.d.ts.map +1 -0
  94. package/dist/middleware/index.js +12 -0
  95. package/dist/middleware/index.js.map +1 -0
  96. package/dist/middleware/mcpi-transport.d.ts +39 -0
  97. package/dist/middleware/mcpi-transport.d.ts.map +1 -0
  98. package/dist/middleware/mcpi-transport.js +121 -0
  99. package/dist/middleware/mcpi-transport.js.map +1 -0
  100. package/dist/middleware/with-mcpi-server.d.ts +78 -0
  101. package/dist/middleware/with-mcpi-server.d.ts.map +1 -0
  102. package/dist/middleware/with-mcpi-server.js +109 -0
  103. package/dist/middleware/with-mcpi-server.js.map +1 -0
  104. package/dist/middleware/with-mcpi.d.ts +202 -0
  105. package/dist/middleware/with-mcpi.d.ts.map +1 -0
  106. package/dist/middleware/with-mcpi.js +625 -0
  107. package/dist/middleware/with-mcpi.js.map +1 -0
  108. package/dist/proof/errors.d.ts +49 -0
  109. package/dist/proof/errors.d.ts.map +1 -0
  110. package/dist/proof/errors.js +61 -0
  111. package/dist/proof/errors.js.map +1 -0
  112. package/dist/proof/generator.d.ts +65 -0
  113. package/dist/proof/generator.d.ts.map +1 -0
  114. package/dist/proof/generator.js +163 -0
  115. package/dist/proof/generator.js.map +1 -0
  116. package/dist/proof/index.d.ts +4 -0
  117. package/dist/proof/index.d.ts.map +1 -0
  118. package/dist/proof/index.js +4 -0
  119. package/dist/proof/index.js.map +1 -0
  120. package/dist/proof/verifier.d.ts +108 -0
  121. package/dist/proof/verifier.d.ts.map +1 -0
  122. package/dist/proof/verifier.js +299 -0
  123. package/dist/proof/verifier.js.map +1 -0
  124. package/dist/providers/base.d.ts +64 -0
  125. package/dist/providers/base.d.ts.map +1 -0
  126. package/dist/providers/base.js +19 -0
  127. package/dist/providers/base.js.map +1 -0
  128. package/dist/providers/index.d.ts +4 -0
  129. package/dist/providers/index.d.ts.map +1 -0
  130. package/dist/providers/index.js +4 -0
  131. package/dist/providers/index.js.map +1 -0
  132. package/dist/providers/memory.d.ts +33 -0
  133. package/dist/providers/memory.d.ts.map +1 -0
  134. package/dist/providers/memory.js +102 -0
  135. package/dist/providers/memory.js.map +1 -0
  136. package/dist/providers/node-crypto.d.ts +26 -0
  137. package/dist/providers/node-crypto.d.ts.map +1 -0
  138. package/dist/providers/node-crypto.js +69 -0
  139. package/dist/providers/node-crypto.js.map +1 -0
  140. package/dist/session/index.d.ts +2 -0
  141. package/dist/session/index.d.ts.map +1 -0
  142. package/dist/session/index.js +2 -0
  143. package/dist/session/index.js.map +1 -0
  144. package/dist/session/manager.d.ts +83 -0
  145. package/dist/session/manager.d.ts.map +1 -0
  146. package/dist/session/manager.js +267 -0
  147. package/dist/session/manager.js.map +1 -0
  148. package/dist/types/protocol.d.ts +320 -0
  149. package/dist/types/protocol.d.ts.map +1 -0
  150. package/dist/types/protocol.js +229 -0
  151. package/dist/types/protocol.js.map +1 -0
  152. package/dist/utils/base58.d.ts +31 -0
  153. package/dist/utils/base58.d.ts.map +1 -0
  154. package/dist/utils/base58.js +104 -0
  155. package/dist/utils/base58.js.map +1 -0
  156. package/dist/utils/base64.d.ts +13 -0
  157. package/dist/utils/base64.d.ts.map +1 -0
  158. package/dist/utils/base64.js +99 -0
  159. package/dist/utils/base64.js.map +1 -0
  160. package/dist/utils/crypto-service.d.ts +37 -0
  161. package/dist/utils/crypto-service.d.ts.map +1 -0
  162. package/dist/utils/crypto-service.js +154 -0
  163. package/dist/utils/crypto-service.js.map +1 -0
  164. package/dist/utils/did-helpers.d.ts +168 -0
  165. package/dist/utils/did-helpers.d.ts.map +1 -0
  166. package/dist/utils/did-helpers.js +211 -0
  167. package/dist/utils/did-helpers.js.map +1 -0
  168. package/dist/utils/ed25519-constants.d.ts +18 -0
  169. package/dist/utils/ed25519-constants.d.ts.map +1 -0
  170. package/dist/utils/ed25519-constants.js +21 -0
  171. package/dist/utils/ed25519-constants.js.map +1 -0
  172. package/dist/utils/index.d.ts +5 -0
  173. package/dist/utils/index.d.ts.map +1 -0
  174. package/dist/utils/index.js +5 -0
  175. package/dist/utils/index.js.map +1 -0
  176. package/package.json +115 -0
  177. package/schemas/README.md +117 -0
  178. package/schemas/delegation-credential.json +312 -0
  179. package/schemas/detached-proof.json +97 -0
  180. package/schemas/handshake-request.json +84 -0
  181. package/schemas/handshake-response.json +67 -0
  182. package/schemas/well-known-mcpi.json +176 -0
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Node.js CryptoProvider
3
+ *
4
+ * Ed25519 crypto backed by Node.js built-in `node:crypto`.
5
+ * Use this on any Node.js 20+ server.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { NodeCryptoProvider } from '@kya-os/mcp/providers';
10
+ * import { withMCPI } from '@kya-os/mcp/middleware';
11
+ *
12
+ * await withMCPI(server, { crypto: new NodeCryptoProvider() });
13
+ * ```
14
+ */
15
+ import { createHash, createPrivateKey, createPublicKey, generateKeyPairSync, sign, verify, randomBytes, } from "node:crypto";
16
+ import { CryptoProvider } from "./base.js";
17
+ /** PKCS8 DER header for Ed25519 private keys (16 bytes) */
18
+ const ED25519_PKCS8_PREFIX = Buffer.from("302e020100300506032b657004220420", "hex");
19
+ /** SPKI DER header for Ed25519 public keys (12 bytes) */
20
+ const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
21
+ export class NodeCryptoProvider extends CryptoProvider {
22
+ async sign(data, privateKeyBase64) {
23
+ const privateKey = Buffer.from(privateKeyBase64, "base64");
24
+ // Handle both raw 32-byte and full 64-byte Ed25519 keys
25
+ const keyBytes = privateKey.length === 64 ? privateKey.subarray(0, 32) : privateKey;
26
+ const keyObject = createPrivateKey({
27
+ key: Buffer.concat([ED25519_PKCS8_PREFIX, keyBytes]),
28
+ format: "der",
29
+ type: "pkcs8",
30
+ });
31
+ return new Uint8Array(sign(null, Buffer.from(data), keyObject));
32
+ }
33
+ async verify(data, signature, publicKeyBase64) {
34
+ try {
35
+ const keyObject = createPublicKey({
36
+ key: Buffer.concat([
37
+ ED25519_SPKI_PREFIX,
38
+ Buffer.from(publicKeyBase64, "base64"),
39
+ ]),
40
+ format: "der",
41
+ type: "spki",
42
+ });
43
+ return verify(null, Buffer.from(data), keyObject, Buffer.from(signature));
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ async generateKeyPair() {
50
+ const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
51
+ publicKeyEncoding: { type: "spki", format: "der" },
52
+ privateKeyEncoding: { type: "pkcs8", format: "der" },
53
+ });
54
+ return {
55
+ privateKey: privateKey.subarray(16, 48).toString("base64"),
56
+ publicKey: publicKey.subarray(12, 44).toString("base64"),
57
+ };
58
+ }
59
+ async hash(data) {
60
+ const hex = createHash("sha256")
61
+ .update(Buffer.from(data))
62
+ .digest("hex");
63
+ return `sha256:${hex}`;
64
+ }
65
+ async randomBytes(length) {
66
+ return new Uint8Array(randomBytes(length));
67
+ }
68
+ }
69
+ //# sourceMappingURL=node-crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-crypto.js","sourceRoot":"","sources":["../../src/providers/node-crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { SessionManager, createHandshakeRequest, validateHandshakeFormat, type SessionConfig, type HandshakeResult, } from './manager.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { SessionManager, createHandshakeRequest, validateHandshakeFormat, } from './manager.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,uBAAuB,GAGxB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Session Management — Platform-agnostic Protocol Reference
3
+ *
4
+ * Handles handshake enforcement, session management, and nonce validation
5
+ * according to MCP-I requirements 4.5–4.9 and 19.1–19.2.
6
+ *
7
+ * Platform adapters inject a CryptoProvider for all random byte generation.
8
+ * The static generateNonce() uses globalThis.crypto (available Node 20+ and
9
+ * Cloudflare Workers) to remain synchronous without platform-specific imports.
10
+ */
11
+ import { type MCPIErrorCode } from "../errors.js";
12
+ import type { HandshakeRequest, SessionContext, NonceCache } from '../types/protocol.js';
13
+ import type { CryptoProvider } from '../providers/base.js';
14
+ export interface SessionConfig {
15
+ timestampSkewSeconds?: number;
16
+ sessionTtlMinutes?: number;
17
+ absoluteSessionLifetime?: number;
18
+ nonceCache?: NonceCache;
19
+ serverDid?: string;
20
+ /** Maximum number of concurrent sessions. Oldest sessions are evicted when exceeded. Default: 10000 */
21
+ maxSessions?: number;
22
+ }
23
+ export interface HandshakeResult {
24
+ success: boolean;
25
+ session?: SessionContext;
26
+ error?: {
27
+ code: MCPIErrorCode;
28
+ message: string;
29
+ remediation?: string;
30
+ };
31
+ }
32
+ export declare class SessionManager {
33
+ private config;
34
+ private cryptoProvider;
35
+ private sessions;
36
+ private sessionInsertionOrder;
37
+ private maxSessions;
38
+ constructor(cryptoProvider: CryptoProvider, config?: SessionConfig);
39
+ setServerDid(serverDid: string): void;
40
+ /**
41
+ * Validate an MCP-I handshake request and create a session.
42
+ *
43
+ * Performs the following checks:
44
+ * - Timestamp within acceptable skew window
45
+ * - Audience matches server DID (if configured)
46
+ * - Nonce not previously used (replay protection)
47
+ *
48
+ * @param request - The handshake request containing nonce, audience, timestamp, and optional agentDid
49
+ * @returns Result object with success flag, session on success, or error details on failure
50
+ */
51
+ validateHandshake(request: HandshakeRequest): Promise<HandshakeResult>;
52
+ /**
53
+ * Retrieve a session by ID, checking for expiration.
54
+ *
55
+ * Updates lastActivity timestamp on successful retrieval (sliding window expiry).
56
+ * Returns null if session doesn't exist, has exceeded idle TTL, or has exceeded
57
+ * absolute lifetime (if configured).
58
+ *
59
+ * @param sessionId - The session ID (e.g., "mcpi_...")
60
+ * @returns Session context if valid, null if expired or not found
61
+ */
62
+ getSession(sessionId: string): Promise<SessionContext | null>;
63
+ private generateSessionId;
64
+ private generateClientId;
65
+ private normalizeClientInfoString;
66
+ private buildClientInfo;
67
+ static generateNonce(): string;
68
+ private evictIfNeeded;
69
+ cleanup(): Promise<void>;
70
+ getStats(): {
71
+ activeSessions: number;
72
+ config: {
73
+ timestampSkewSeconds: number;
74
+ sessionTtlMinutes: number;
75
+ absoluteSessionLifetime?: number;
76
+ cacheType: string;
77
+ };
78
+ };
79
+ clearSessions(): void;
80
+ }
81
+ export declare function createHandshakeRequest(audience: string): HandshakeRequest;
82
+ export declare function validateHandshakeFormat(request: unknown): request is HandshakeRequest;
83
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,UAAU,EACX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,MAAM,WAAW,aAAa;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uGAAuG;IACvG,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,aAAa,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAGZ;IACF,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,qBAAqB,CAAgB;IAC7C,OAAO,CAAC,WAAW,CAAS;gBAEhB,cAAc,EAAE,cAAc,EAAE,MAAM,GAAE,aAAkB;IAsBtE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrC;;;;;;;;;;OAUG;IACG,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkF5E;;;;;;;;;OASG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;YA2BrD,iBAAiB;YAWjB,gBAAgB;IAQ9B,OAAO,CAAC,yBAAyB;YAMnB,eAAe;IA2B7B,MAAM,CAAC,aAAa,IAAI,MAAM;IAa9B,OAAO,CAAC,aAAa;IASf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA0B9B,QAAQ,IAAI;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE;YACN,oBAAoB,EAAE,MAAM,CAAC;YAC7B,iBAAiB,EAAE,MAAM,CAAC;YAC1B,uBAAuB,CAAC,EAAE,MAAM,CAAC;YACjC,SAAS,EAAE,MAAM,CAAC;SACnB,CAAC;KACH;IAYD,aAAa,IAAI,IAAI;CAItB;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAMzE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB,CAYrF"}
@@ -0,0 +1,267 @@
1
+ /**
2
+ * Session Management — Platform-agnostic Protocol Reference
3
+ *
4
+ * Handles handshake enforcement, session management, and nonce validation
5
+ * according to MCP-I requirements 4.5–4.9 and 19.1–19.2.
6
+ *
7
+ * Platform adapters inject a CryptoProvider for all random byte generation.
8
+ * The static generateNonce() uses globalThis.crypto (available Node 20+ and
9
+ * Cloudflare Workers) to remain synchronous without platform-specific imports.
10
+ */
11
+ import { MCPI_ERROR_CODES } from "../errors.js";
12
+ import { MemoryNonceCacheProvider } from '../providers/memory.js';
13
+ import { logger } from '../logging/index.js';
14
+ export class SessionManager {
15
+ config;
16
+ cryptoProvider;
17
+ sessions = new Map();
18
+ sessionInsertionOrder = [];
19
+ maxSessions;
20
+ constructor(cryptoProvider, config = {}) {
21
+ this.cryptoProvider = cryptoProvider;
22
+ this.maxSessions = config.maxSessions ?? 10_000;
23
+ this.config = {
24
+ timestampSkewSeconds: config.timestampSkewSeconds ?? 120,
25
+ sessionTtlMinutes: config.sessionTtlMinutes ?? 30,
26
+ nonceCache: config.nonceCache ?? new MemoryNonceCacheProvider(),
27
+ ...(config.absoluteSessionLifetime !== undefined && {
28
+ absoluteSessionLifetime: config.absoluteSessionLifetime,
29
+ }),
30
+ ...(config.serverDid !== undefined && { serverDid: config.serverDid }),
31
+ };
32
+ if (this.config.nonceCache instanceof MemoryNonceCacheProvider) {
33
+ logger.warn('[SessionManager] Using MemoryNonceCacheProvider — not suitable for ' +
34
+ 'multi-instance deployments. Use Redis, DynamoDB, or Cloudflare KV ' +
35
+ 'for production.');
36
+ }
37
+ }
38
+ setServerDid(serverDid) {
39
+ this.config.serverDid = serverDid;
40
+ }
41
+ /**
42
+ * Validate an MCP-I handshake request and create a session.
43
+ *
44
+ * Performs the following checks:
45
+ * - Timestamp within acceptable skew window
46
+ * - Audience matches server DID (if configured)
47
+ * - Nonce not previously used (replay protection)
48
+ *
49
+ * @param request - The handshake request containing nonce, audience, timestamp, and optional agentDid
50
+ * @returns Result object with success flag, session on success, or error details on failure
51
+ */
52
+ async validateHandshake(request) {
53
+ try {
54
+ const now = Math.floor(Date.now() / 1000);
55
+ const timeDiff = Math.abs(now - request.timestamp);
56
+ if (timeDiff > this.config.timestampSkewSeconds) {
57
+ return {
58
+ success: false,
59
+ error: {
60
+ code: MCPI_ERROR_CODES.handshake_failed,
61
+ message: `Timestamp outside acceptable range (±${this.config.timestampSkewSeconds}s)`,
62
+ remediation: `Check NTP sync on client and server. Current server time: ${now}, received: ${request.timestamp}, diff: ${timeDiff}s. Adjust timestampSkewSeconds if needed.`,
63
+ },
64
+ };
65
+ }
66
+ // Validate audience matches this server's DID (SPEC.md §4 MUST)
67
+ if (this.config.serverDid && request.audience !== this.config.serverDid) {
68
+ return {
69
+ success: false,
70
+ error: {
71
+ code: MCPI_ERROR_CODES.handshake_failed,
72
+ message: `Audience mismatch: expected ${this.config.serverDid}, got ${request.audience}`,
73
+ },
74
+ };
75
+ }
76
+ const nonceExists = await this.config.nonceCache.has(request.nonce, request.agentDid);
77
+ if (nonceExists) {
78
+ return {
79
+ success: false,
80
+ error: {
81
+ code: MCPI_ERROR_CODES.handshake_failed,
82
+ message: 'Nonce already used (replay attack prevention)',
83
+ remediation: 'Generate a new unique nonce for each request',
84
+ },
85
+ };
86
+ }
87
+ const nonceTtlSeconds = this.config.sessionTtlMinutes * 60 + 60;
88
+ await this.config.nonceCache.add(request.nonce, nonceTtlSeconds, request.agentDid);
89
+ const sessionId = await this.generateSessionId();
90
+ const clientInfo = await this.buildClientInfo(request);
91
+ const session = {
92
+ sessionId,
93
+ audience: request.audience,
94
+ nonce: request.nonce,
95
+ timestamp: request.timestamp,
96
+ createdAt: now,
97
+ lastActivity: now,
98
+ ttlMinutes: this.config.sessionTtlMinutes,
99
+ identityState: 'anonymous',
100
+ agentDid: request.agentDid,
101
+ ...(this.config.serverDid && { serverDid: this.config.serverDid }),
102
+ ...(clientInfo && { clientInfo }),
103
+ };
104
+ this.evictIfNeeded();
105
+ this.sessions.set(sessionId, session);
106
+ this.sessionInsertionOrder.push(sessionId);
107
+ return { success: true, session };
108
+ }
109
+ catch (error) {
110
+ return {
111
+ success: false,
112
+ error: {
113
+ code: MCPI_ERROR_CODES.handshake_failed,
114
+ message: `Handshake validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
115
+ },
116
+ };
117
+ }
118
+ }
119
+ /**
120
+ * Retrieve a session by ID, checking for expiration.
121
+ *
122
+ * Updates lastActivity timestamp on successful retrieval (sliding window expiry).
123
+ * Returns null if session doesn't exist, has exceeded idle TTL, or has exceeded
124
+ * absolute lifetime (if configured).
125
+ *
126
+ * @param sessionId - The session ID (e.g., "mcpi_...")
127
+ * @returns Session context if valid, null if expired or not found
128
+ */
129
+ async getSession(sessionId) {
130
+ const session = this.sessions.get(sessionId);
131
+ if (!session)
132
+ return null;
133
+ const now = Math.floor(Date.now() / 1000);
134
+ const idleTimeSeconds = now - session.lastActivity;
135
+ const maxIdleSeconds = session.ttlMinutes * 60;
136
+ if (idleTimeSeconds > maxIdleSeconds) {
137
+ this.sessions.delete(sessionId);
138
+ return null;
139
+ }
140
+ if (this.config.absoluteSessionLifetime !== undefined) {
141
+ const sessionAgeSeconds = now - session.createdAt;
142
+ const maxAgeSeconds = this.config.absoluteSessionLifetime * 60;
143
+ if (sessionAgeSeconds > maxAgeSeconds) {
144
+ this.sessions.delete(sessionId);
145
+ return null;
146
+ }
147
+ }
148
+ session.lastActivity = now;
149
+ this.sessions.set(sessionId, session);
150
+ return session;
151
+ }
152
+ async generateSessionId() {
153
+ const bytes = await this.cryptoProvider.randomBytes(16);
154
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
155
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
156
+ const hex = Array.from(bytes)
157
+ .map((b) => b.toString(16).padStart(2, '0'))
158
+ .join('');
159
+ const uuid = `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
160
+ return `mcpi_${uuid}`;
161
+ }
162
+ async generateClientId() {
163
+ const bytes = await this.cryptoProvider.randomBytes(6);
164
+ const hex = Array.from(bytes)
165
+ .map((b) => b.toString(16).padStart(2, '0'))
166
+ .join('');
167
+ return `client_${hex}`;
168
+ }
169
+ normalizeClientInfoString(value) {
170
+ if (typeof value !== 'string')
171
+ return undefined;
172
+ const trimmed = value.trim();
173
+ return trimmed.length > 0 ? trimmed : undefined;
174
+ }
175
+ async buildClientInfo(request) {
176
+ const hasMetadata = !!request.clientInfo ||
177
+ typeof request.clientProtocolVersion === 'string' ||
178
+ request.clientCapabilities !== undefined;
179
+ if (!hasMetadata)
180
+ return undefined;
181
+ const source = request.clientInfo;
182
+ return {
183
+ name: this.normalizeClientInfoString(source?.name) ?? 'unknown',
184
+ title: this.normalizeClientInfoString(source?.title),
185
+ version: this.normalizeClientInfoString(source?.version),
186
+ platform: this.normalizeClientInfoString(source?.platform),
187
+ vendor: this.normalizeClientInfoString(source?.vendor),
188
+ persistentId: this.normalizeClientInfoString(source?.persistentId),
189
+ clientId: this.normalizeClientInfoString(source?.clientId) ??
190
+ (await this.generateClientId()),
191
+ protocolVersion: this.normalizeClientInfoString(request.clientProtocolVersion),
192
+ capabilities: request.clientCapabilities,
193
+ };
194
+ }
195
+ static generateNonce() {
196
+ const buffer = new Uint8Array(16);
197
+ globalThis.crypto.getRandomValues(buffer);
198
+ let binaryStr = '';
199
+ for (let i = 0; i < buffer.length; i++) {
200
+ binaryStr += String.fromCharCode(buffer[i]);
201
+ }
202
+ return btoa(binaryStr)
203
+ .replace(/\+/g, '-')
204
+ .replace(/\//g, '_')
205
+ .replace(/=/g, '');
206
+ }
207
+ evictIfNeeded() {
208
+ while (this.sessions.size >= this.maxSessions && this.sessionInsertionOrder.length > 0) {
209
+ const oldest = this.sessionInsertionOrder.shift();
210
+ if (oldest) {
211
+ this.sessions.delete(oldest);
212
+ }
213
+ }
214
+ }
215
+ async cleanup() {
216
+ const now = Math.floor(Date.now() / 1000);
217
+ for (const [sessionId, session] of this.sessions.entries()) {
218
+ const idleTimeSeconds = now - session.lastActivity;
219
+ const maxIdleSeconds = session.ttlMinutes * 60;
220
+ let expired = idleTimeSeconds > maxIdleSeconds;
221
+ if (!expired && this.config.absoluteSessionLifetime !== undefined) {
222
+ const sessionAgeSeconds = now - session.createdAt;
223
+ const maxAgeSeconds = this.config.absoluteSessionLifetime * 60;
224
+ expired = sessionAgeSeconds > maxAgeSeconds;
225
+ }
226
+ if (expired) {
227
+ this.sessions.delete(sessionId);
228
+ }
229
+ }
230
+ this.sessionInsertionOrder = this.sessionInsertionOrder.filter(id => this.sessions.has(id));
231
+ await this.config.nonceCache.cleanup();
232
+ }
233
+ getStats() {
234
+ return {
235
+ activeSessions: this.sessions.size,
236
+ config: {
237
+ timestampSkewSeconds: this.config.timestampSkewSeconds,
238
+ sessionTtlMinutes: this.config.sessionTtlMinutes,
239
+ absoluteSessionLifetime: this.config.absoluteSessionLifetime,
240
+ cacheType: this.config.nonceCache.constructor.name,
241
+ },
242
+ };
243
+ }
244
+ clearSessions() {
245
+ this.sessions.clear();
246
+ this.sessionInsertionOrder = [];
247
+ }
248
+ }
249
+ export function createHandshakeRequest(audience) {
250
+ return {
251
+ nonce: SessionManager.generateNonce(),
252
+ audience,
253
+ timestamp: Math.floor(Date.now() / 1000),
254
+ };
255
+ }
256
+ export function validateHandshakeFormat(request) {
257
+ return (typeof request === 'object' &&
258
+ request !== null &&
259
+ typeof request['nonce'] === 'string' &&
260
+ request['nonce'].length > 0 &&
261
+ typeof request['audience'] === 'string' &&
262
+ request['audience'].length > 0 &&
263
+ typeof request['timestamp'] === 'number' &&
264
+ request['timestamp'] > 0 &&
265
+ Number.isInteger(request['timestamp']));
266
+ }
267
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/session/manager.ts"],"names":[],"mappings":"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"}