@kya-os/mcp-i-core 1.4.18 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +14 -0
- package/dist/auth/handshake.d.ts +119 -0
- package/dist/auth/handshake.js +250 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.js +11 -0
- package/dist/auth/types.d.ts +46 -0
- package/dist/auth/types.js +10 -0
- package/dist/delegation/index.d.ts +1 -0
- package/dist/delegation/index.js +1 -0
- package/dist/delegation/outbound-proof.d.ts +70 -0
- package/dist/delegation/outbound-proof.js +67 -0
- package/dist/identity/user-did-manager.js +5 -3
- package/dist/index.d.ts +5 -0
- package/dist/index.js +25 -2
- package/dist/proof/generator.d.ts +109 -0
- package/dist/proof/generator.js +236 -0
- package/dist/proof/index.d.ts +5 -0
- package/dist/proof/index.js +11 -0
- package/dist/providers/base.d.ts +5 -1
- package/dist/runtime/base.d.ts +127 -13
- package/dist/runtime/base.js +199 -51
- package/dist/runtime/ext-apps-constants.d.ts +14 -0
- package/dist/runtime/ext-apps-constants.js +17 -0
- package/dist/services/batch-delegation.service.d.ts +1 -1
- package/dist/services/batch-delegation.service.js +4 -4
- package/dist/services/proof-verifier.js +1 -1
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.js +11 -0
- package/dist/session/manager.d.ts +113 -0
- package/dist/session/manager.js +273 -0
- package/docs/API_REFERENCE.md +76 -0
- package/docs/COMPLIANCE_MATRIX.md +691 -0
- package/docs/STATUSLIST2021_GUIDE.md +696 -0
- package/docs/W3C_VC_DELEGATION_GUIDE.md +710 -0
- package/package.json +22 -6
- package/vitest.config.mts +8 -7
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Apps Extension Constants
|
|
3
|
+
*
|
|
4
|
+
* Shared constants for the MCP Apps consent UI integration.
|
|
5
|
+
* Kept separate from the runtime class so consumers can import
|
|
6
|
+
* without pulling in the full MCPIRuntimeBase dependency.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* URI for the shared consent UI resource.
|
|
10
|
+
* All consent-requiring tools reference this single resource;
|
|
11
|
+
* tool-specific data is passed via structuredContent.
|
|
12
|
+
*/
|
|
13
|
+
export declare const CONSENT_UI_RESOURCE_URI = "ui://mcpi-consent/authorize";
|
|
14
|
+
//# sourceMappingURL=ext-apps-constants.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Apps Extension Constants
|
|
4
|
+
*
|
|
5
|
+
* Shared constants for the MCP Apps consent UI integration.
|
|
6
|
+
* Kept separate from the runtime class so consumers can import
|
|
7
|
+
* without pulling in the full MCPIRuntimeBase dependency.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.CONSENT_UI_RESOURCE_URI = void 0;
|
|
11
|
+
/**
|
|
12
|
+
* URI for the shared consent UI resource.
|
|
13
|
+
* All consent-requiring tools reference this single resource;
|
|
14
|
+
* tool-specific data is passed via structuredContent.
|
|
15
|
+
*/
|
|
16
|
+
exports.CONSENT_UI_RESOURCE_URI = "ui://mcpi-consent/authorize";
|
|
17
|
+
//# sourceMappingURL=ext-apps-constants.js.map
|
|
@@ -48,6 +48,6 @@ export declare class BatchDelegationService {
|
|
|
48
48
|
* @param agentDid - Agent DID for fetching tool protections
|
|
49
49
|
* @returns Array of tool names requiring the specified provider
|
|
50
50
|
*/
|
|
51
|
-
getToolsForProvider(
|
|
51
|
+
getToolsForProvider(_provider: string, _projectId: string, _agentDid: string): Promise<string[]>;
|
|
52
52
|
}
|
|
53
53
|
//# sourceMappingURL=batch-delegation.service.d.ts.map
|
|
@@ -84,10 +84,10 @@ class BatchDelegationService {
|
|
|
84
84
|
* @param agentDid - Agent DID for fetching tool protections
|
|
85
85
|
* @returns Array of tool names requiring the specified provider
|
|
86
86
|
*/
|
|
87
|
-
async getToolsForProvider(
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
// TODO: Implement
|
|
87
|
+
async getToolsForProvider(_provider, _projectId, _agentDid) {
|
|
88
|
+
// Stub implementation: Returns empty array.
|
|
89
|
+
// Full implementation would fetch all tool protections and filter by provider.
|
|
90
|
+
// TODO(feature): Implement when batch delegation UI requires provider-based tool grouping.
|
|
91
91
|
return [];
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -23,7 +23,7 @@ class ProofVerifier {
|
|
|
23
23
|
this.clock = config.clockProvider;
|
|
24
24
|
this.nonceCache = config.nonceCacheProvider;
|
|
25
25
|
this.fetch = config.fetchProvider;
|
|
26
|
-
this.timestampSkewSeconds = config.timestampSkewSeconds ??
|
|
26
|
+
this.timestampSkewSeconds = config.timestampSkewSeconds ?? 300; // Default 5 minutes
|
|
27
27
|
this.nonceTtlSeconds = config.nonceTtlSeconds ?? 300; // Default 5 minutes
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateHandshakeFormat = exports.createHandshakeRequest = exports.SessionManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Session module — platform-agnostic session management reference implementation.
|
|
6
|
+
*/
|
|
7
|
+
var manager_1 = require("./manager");
|
|
8
|
+
Object.defineProperty(exports, "SessionManager", { enumerable: true, get: function () { return manager_1.SessionManager; } });
|
|
9
|
+
Object.defineProperty(exports, "createHandshakeRequest", { enumerable: true, get: function () { return manager_1.createHandshakeRequest; } });
|
|
10
|
+
Object.defineProperty(exports, "validateHandshakeFormat", { enumerable: true, get: function () { return manager_1.validateHandshakeFormat; } });
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,113 @@
|
|
|
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 { HandshakeRequest, SessionContext, NonceCache } from "@kya-os/contracts/handshake";
|
|
12
|
+
import { CryptoProvider } from "../providers/base";
|
|
13
|
+
/**
|
|
14
|
+
* Session management configuration
|
|
15
|
+
*/
|
|
16
|
+
export interface SessionConfig {
|
|
17
|
+
/** Clock-skew tolerance in seconds. Default: 120. */
|
|
18
|
+
timestampSkewSeconds?: number;
|
|
19
|
+
/** Idle session TTL in minutes. Default: 30. */
|
|
20
|
+
sessionTtlMinutes?: number;
|
|
21
|
+
/** Optional absolute session lifetime in minutes. */
|
|
22
|
+
absoluteSessionLifetime?: number;
|
|
23
|
+
/** Nonce cache implementation. Default: MemoryNonceCacheProvider. */
|
|
24
|
+
nonceCache?: NonceCache;
|
|
25
|
+
/** Optional server DID to include in session context. */
|
|
26
|
+
serverDid?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Handshake validation result
|
|
30
|
+
*/
|
|
31
|
+
export interface HandshakeResult {
|
|
32
|
+
success: boolean;
|
|
33
|
+
session?: SessionContext;
|
|
34
|
+
error?: {
|
|
35
|
+
code: string;
|
|
36
|
+
message: string;
|
|
37
|
+
remediation?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Platform-agnostic session manager.
|
|
42
|
+
* Requires a CryptoProvider for session ID and client ID generation.
|
|
43
|
+
*/
|
|
44
|
+
export declare class SessionManager {
|
|
45
|
+
private config;
|
|
46
|
+
private cryptoProvider;
|
|
47
|
+
private sessions;
|
|
48
|
+
constructor(cryptoProvider: CryptoProvider, config?: SessionConfig);
|
|
49
|
+
/**
|
|
50
|
+
* Set server DID for session creation (called after identity is loaded).
|
|
51
|
+
*/
|
|
52
|
+
setServerDid(serverDid: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* Validate handshake and create or retrieve session.
|
|
55
|
+
* Requirements: 4.5, 4.6, 4.7, 4.8, 4.9
|
|
56
|
+
*/
|
|
57
|
+
validateHandshake(request: HandshakeRequest): Promise<HandshakeResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Get session by ID and update last activity.
|
|
60
|
+
*/
|
|
61
|
+
getSession(sessionId: string): Promise<SessionContext | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Generate a unique session ID (mcpi_{uuid} format).
|
|
64
|
+
* Uses injected CryptoProvider for platform-agnostic random bytes.
|
|
65
|
+
*/
|
|
66
|
+
private generateSessionId;
|
|
67
|
+
/**
|
|
68
|
+
* Generate a deterministic client identifier.
|
|
69
|
+
*/
|
|
70
|
+
private generateClientId;
|
|
71
|
+
/**
|
|
72
|
+
* Normalize string fields from handshake metadata.
|
|
73
|
+
*/
|
|
74
|
+
private normalizeClientInfoString;
|
|
75
|
+
/**
|
|
76
|
+
* Build MCP client metadata for the session.
|
|
77
|
+
*/
|
|
78
|
+
private buildClientInfo;
|
|
79
|
+
/**
|
|
80
|
+
* Generate a cryptographically secure nonce.
|
|
81
|
+
* Uses globalThis.crypto (sync Web Crypto — available in Node 20+ and Workers).
|
|
82
|
+
*/
|
|
83
|
+
static generateNonce(): string;
|
|
84
|
+
/**
|
|
85
|
+
* Cleanup expired sessions and nonces.
|
|
86
|
+
*/
|
|
87
|
+
cleanup(): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Get session statistics.
|
|
90
|
+
*/
|
|
91
|
+
getStats(): {
|
|
92
|
+
activeSessions: number;
|
|
93
|
+
config: {
|
|
94
|
+
timestampSkewSeconds: number;
|
|
95
|
+
sessionTtlMinutes: number;
|
|
96
|
+
absoluteSessionLifetime?: number;
|
|
97
|
+
cacheType: string;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Clear all sessions (useful for testing).
|
|
102
|
+
*/
|
|
103
|
+
clearSessions(): void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Create a handshake request with a secure nonce.
|
|
107
|
+
*/
|
|
108
|
+
export declare function createHandshakeRequest(audience: string): HandshakeRequest;
|
|
109
|
+
/**
|
|
110
|
+
* Validate handshake request format.
|
|
111
|
+
*/
|
|
112
|
+
export declare function validateHandshakeFormat(request: unknown): request is HandshakeRequest;
|
|
113
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Session Management — Platform-agnostic Protocol Reference
|
|
4
|
+
*
|
|
5
|
+
* Handles handshake enforcement, session management, and nonce validation
|
|
6
|
+
* according to MCP-I requirements 4.5–4.9 and 19.1–19.2.
|
|
7
|
+
*
|
|
8
|
+
* Platform adapters inject a CryptoProvider for all random byte generation.
|
|
9
|
+
* The static generateNonce() uses globalThis.crypto (available Node 20+ and
|
|
10
|
+
* Cloudflare Workers) to remain synchronous without platform-specific imports.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.SessionManager = void 0;
|
|
14
|
+
exports.createHandshakeRequest = createHandshakeRequest;
|
|
15
|
+
exports.validateHandshakeFormat = validateHandshakeFormat;
|
|
16
|
+
const memory_1 = require("../providers/memory");
|
|
17
|
+
const logging_1 = require("../logging");
|
|
18
|
+
/**
|
|
19
|
+
* Platform-agnostic session manager.
|
|
20
|
+
* Requires a CryptoProvider for session ID and client ID generation.
|
|
21
|
+
*/
|
|
22
|
+
class SessionManager {
|
|
23
|
+
config;
|
|
24
|
+
cryptoProvider;
|
|
25
|
+
sessions = new Map();
|
|
26
|
+
constructor(cryptoProvider, config = {}) {
|
|
27
|
+
this.cryptoProvider = cryptoProvider;
|
|
28
|
+
this.config = {
|
|
29
|
+
timestampSkewSeconds: config.timestampSkewSeconds ?? 120,
|
|
30
|
+
sessionTtlMinutes: config.sessionTtlMinutes ?? 30,
|
|
31
|
+
nonceCache: config.nonceCache ?? new memory_1.MemoryNonceCacheProvider(),
|
|
32
|
+
...(config.absoluteSessionLifetime !== undefined && {
|
|
33
|
+
absoluteSessionLifetime: config.absoluteSessionLifetime,
|
|
34
|
+
}),
|
|
35
|
+
...(config.serverDid !== undefined && { serverDid: config.serverDid }),
|
|
36
|
+
};
|
|
37
|
+
if (this.config.nonceCache instanceof memory_1.MemoryNonceCacheProvider) {
|
|
38
|
+
logging_1.logger.warn("[SessionManager] Using MemoryNonceCacheProvider — not suitable for " +
|
|
39
|
+
"multi-instance deployments. Use Redis, DynamoDB, or Cloudflare KV " +
|
|
40
|
+
"for production.");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Set server DID for session creation (called after identity is loaded).
|
|
45
|
+
*/
|
|
46
|
+
setServerDid(serverDid) {
|
|
47
|
+
this.config.serverDid = serverDid;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Validate handshake and create or retrieve session.
|
|
51
|
+
* Requirements: 4.5, 4.6, 4.7, 4.8, 4.9
|
|
52
|
+
*/
|
|
53
|
+
async validateHandshake(request) {
|
|
54
|
+
try {
|
|
55
|
+
const now = Math.floor(Date.now() / 1000);
|
|
56
|
+
const timeDiff = Math.abs(now - request.timestamp);
|
|
57
|
+
if (timeDiff > this.config.timestampSkewSeconds) {
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
error: {
|
|
61
|
+
code: "XMCP_I_EHANDSHAKE",
|
|
62
|
+
message: `Timestamp outside acceptable range (±${this.config.timestampSkewSeconds}s)`,
|
|
63
|
+
remediation: `Check NTP sync on client and server. Current server time: ${now}, received: ${request.timestamp}, diff: ${timeDiff}s. Adjust timestampSkewSeconds if needed.`,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const nonceExists = await this.config.nonceCache.has(request.nonce, request.agentDid);
|
|
68
|
+
if (nonceExists) {
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: {
|
|
72
|
+
code: "XMCP_I_EHANDSHAKE",
|
|
73
|
+
message: "Nonce already used (replay attack prevention)",
|
|
74
|
+
remediation: "Generate a new unique nonce for each request",
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const nonceTtlSeconds = this.config.sessionTtlMinutes * 60 + 60;
|
|
79
|
+
await this.config.nonceCache.add(request.nonce, nonceTtlSeconds, request.agentDid);
|
|
80
|
+
const sessionId = await this.generateSessionId();
|
|
81
|
+
const clientInfo = await this.buildClientInfo(request);
|
|
82
|
+
const session = {
|
|
83
|
+
sessionId,
|
|
84
|
+
audience: request.audience,
|
|
85
|
+
nonce: request.nonce,
|
|
86
|
+
timestamp: request.timestamp,
|
|
87
|
+
createdAt: now,
|
|
88
|
+
lastActivity: now,
|
|
89
|
+
ttlMinutes: this.config.sessionTtlMinutes,
|
|
90
|
+
identityState: "anonymous",
|
|
91
|
+
agentDid: request.agentDid,
|
|
92
|
+
...(this.config.serverDid && { serverDid: this.config.serverDid }),
|
|
93
|
+
...(clientInfo && { clientInfo }),
|
|
94
|
+
};
|
|
95
|
+
this.sessions.set(sessionId, session);
|
|
96
|
+
return { success: true, session };
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return {
|
|
100
|
+
success: false,
|
|
101
|
+
error: {
|
|
102
|
+
code: "XMCP_I_EHANDSHAKE",
|
|
103
|
+
message: `Handshake validation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get session by ID and update last activity.
|
|
110
|
+
*/
|
|
111
|
+
async getSession(sessionId) {
|
|
112
|
+
const session = this.sessions.get(sessionId);
|
|
113
|
+
if (!session)
|
|
114
|
+
return null;
|
|
115
|
+
const now = Math.floor(Date.now() / 1000);
|
|
116
|
+
const idleTimeSeconds = now - session.lastActivity;
|
|
117
|
+
const maxIdleSeconds = session.ttlMinutes * 60;
|
|
118
|
+
if (idleTimeSeconds > maxIdleSeconds) {
|
|
119
|
+
this.sessions.delete(sessionId);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
if (this.config.absoluteSessionLifetime !== undefined) {
|
|
123
|
+
const sessionAgeSeconds = now - session.createdAt;
|
|
124
|
+
const maxAgeSeconds = this.config.absoluteSessionLifetime * 60;
|
|
125
|
+
if (sessionAgeSeconds > maxAgeSeconds) {
|
|
126
|
+
this.sessions.delete(sessionId);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
session.lastActivity = now;
|
|
131
|
+
this.sessions.set(sessionId, session);
|
|
132
|
+
return session;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Generate a unique session ID (mcpi_{uuid} format).
|
|
136
|
+
* Uses injected CryptoProvider for platform-agnostic random bytes.
|
|
137
|
+
*/
|
|
138
|
+
async generateSessionId() {
|
|
139
|
+
const bytes = await this.cryptoProvider.randomBytes(16);
|
|
140
|
+
// Apply UUID v4 version and variant bits
|
|
141
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
142
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
143
|
+
const hex = Array.from(bytes)
|
|
144
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
145
|
+
.join("");
|
|
146
|
+
const uuid = `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
147
|
+
return `mcpi_${uuid}`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Generate a deterministic client identifier.
|
|
151
|
+
*/
|
|
152
|
+
async generateClientId() {
|
|
153
|
+
const bytes = await this.cryptoProvider.randomBytes(6);
|
|
154
|
+
const hex = Array.from(bytes)
|
|
155
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
156
|
+
.join("");
|
|
157
|
+
return `client_${hex}`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Normalize string fields from handshake metadata.
|
|
161
|
+
*/
|
|
162
|
+
normalizeClientInfoString(value) {
|
|
163
|
+
if (typeof value !== "string")
|
|
164
|
+
return undefined;
|
|
165
|
+
const trimmed = value.trim();
|
|
166
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Build MCP client metadata for the session.
|
|
170
|
+
*/
|
|
171
|
+
async buildClientInfo(request) {
|
|
172
|
+
const hasMetadata = !!request.clientInfo ||
|
|
173
|
+
typeof request.clientProtocolVersion === "string" ||
|
|
174
|
+
request.clientCapabilities !== undefined;
|
|
175
|
+
if (!hasMetadata)
|
|
176
|
+
return undefined;
|
|
177
|
+
const source = request.clientInfo;
|
|
178
|
+
return {
|
|
179
|
+
name: this.normalizeClientInfoString(source?.name) ?? "unknown",
|
|
180
|
+
title: this.normalizeClientInfoString(source?.title),
|
|
181
|
+
version: this.normalizeClientInfoString(source?.version),
|
|
182
|
+
platform: this.normalizeClientInfoString(source?.platform),
|
|
183
|
+
vendor: this.normalizeClientInfoString(source?.vendor),
|
|
184
|
+
persistentId: this.normalizeClientInfoString(source?.persistentId),
|
|
185
|
+
clientId: this.normalizeClientInfoString(source?.clientId) ??
|
|
186
|
+
(await this.generateClientId()),
|
|
187
|
+
protocolVersion: this.normalizeClientInfoString(request.clientProtocolVersion),
|
|
188
|
+
capabilities: request.clientCapabilities,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Generate a cryptographically secure nonce.
|
|
193
|
+
* Uses globalThis.crypto (sync Web Crypto — available in Node 20+ and Workers).
|
|
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
|
+
/**
|
|
208
|
+
* Cleanup expired sessions and nonces.
|
|
209
|
+
*/
|
|
210
|
+
async cleanup() {
|
|
211
|
+
const now = Math.floor(Date.now() / 1000);
|
|
212
|
+
for (const [sessionId, session] of this.sessions.entries()) {
|
|
213
|
+
const idleTimeSeconds = now - session.lastActivity;
|
|
214
|
+
const maxIdleSeconds = session.ttlMinutes * 60;
|
|
215
|
+
let expired = idleTimeSeconds > maxIdleSeconds;
|
|
216
|
+
if (!expired && this.config.absoluteSessionLifetime !== undefined) {
|
|
217
|
+
const sessionAgeSeconds = now - session.createdAt;
|
|
218
|
+
const maxAgeSeconds = this.config.absoluteSessionLifetime * 60;
|
|
219
|
+
expired = sessionAgeSeconds > maxAgeSeconds;
|
|
220
|
+
}
|
|
221
|
+
if (expired) {
|
|
222
|
+
this.sessions.delete(sessionId);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
await this.config.nonceCache.cleanup();
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get session statistics.
|
|
229
|
+
*/
|
|
230
|
+
getStats() {
|
|
231
|
+
return {
|
|
232
|
+
activeSessions: this.sessions.size,
|
|
233
|
+
config: {
|
|
234
|
+
timestampSkewSeconds: this.config.timestampSkewSeconds,
|
|
235
|
+
sessionTtlMinutes: this.config.sessionTtlMinutes,
|
|
236
|
+
absoluteSessionLifetime: this.config.absoluteSessionLifetime,
|
|
237
|
+
cacheType: this.config.nonceCache.constructor.name,
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Clear all sessions (useful for testing).
|
|
243
|
+
*/
|
|
244
|
+
clearSessions() {
|
|
245
|
+
this.sessions.clear();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
exports.SessionManager = SessionManager;
|
|
249
|
+
/**
|
|
250
|
+
* Create a handshake request with a secure nonce.
|
|
251
|
+
*/
|
|
252
|
+
function createHandshakeRequest(audience) {
|
|
253
|
+
return {
|
|
254
|
+
nonce: SessionManager.generateNonce(),
|
|
255
|
+
audience,
|
|
256
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Validate handshake request format.
|
|
261
|
+
*/
|
|
262
|
+
function validateHandshakeFormat(request) {
|
|
263
|
+
return (typeof request === "object" &&
|
|
264
|
+
request !== null &&
|
|
265
|
+
typeof request.nonce === "string" &&
|
|
266
|
+
request.nonce.length > 0 &&
|
|
267
|
+
typeof request.audience === "string" &&
|
|
268
|
+
request.audience.length > 0 &&
|
|
269
|
+
typeof request.timestamp === "number" &&
|
|
270
|
+
request.timestamp > 0 &&
|
|
271
|
+
Number.isInteger(request.timestamp));
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Full API reference for `@kya-os/mcp-i-core` package.
|
|
4
|
+
|
|
5
|
+
> **Note:** This reference is being updated. For complete API signatures, see the TypeScript type definitions in `src/index.ts` which exports all public interfaces.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @kya-os/mcp-i-core
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @kya-os/mcp-i-core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Core Exports
|
|
16
|
+
|
|
17
|
+
### Runtime
|
|
18
|
+
|
|
19
|
+
- **MCPIRuntimeBase** - Provider-based runtime class for MCP-I operations
|
|
20
|
+
|
|
21
|
+
### Delegation (W3C VC-based)
|
|
22
|
+
|
|
23
|
+
- **DelegationCredentialIssuer** - Issues W3C Verifiable Credentials for delegations
|
|
24
|
+
- **DelegationCredentialVerifier** - Verifies delegation credentials with DID resolution
|
|
25
|
+
- **StatusList2021Manager** - Manages StatusList2021 credentials for revocation
|
|
26
|
+
- **DelegationGraphManager** - Manages delegation relationships and chains
|
|
27
|
+
- **CascadingRevocationManager** - Handles cascading revocation through delegation chains
|
|
28
|
+
|
|
29
|
+
### Services
|
|
30
|
+
|
|
31
|
+
- **ToolProtectionService** - Manages tool-level delegation requirements
|
|
32
|
+
- **PolicyService** - Evaluates access policies
|
|
33
|
+
- **CryptoService** - Cryptographic operations (JWS, signatures)
|
|
34
|
+
- **ProofVerifier** - Verifies detached proofs
|
|
35
|
+
- **OAuthService** - OAuth 2.0 with PKCE support
|
|
36
|
+
- **AccessControlApiService** - AgentShield API integration
|
|
37
|
+
|
|
38
|
+
### Providers (Abstract)
|
|
39
|
+
|
|
40
|
+
- **CryptoProvider** - Cryptographic operations interface
|
|
41
|
+
- **IdentityProvider** - Agent identity management
|
|
42
|
+
- **ClockProvider** - Time operations
|
|
43
|
+
- **FetchProvider** - Network operations
|
|
44
|
+
- **StorageProvider** - Key-value storage
|
|
45
|
+
- **NonceCacheProvider** - Replay attack prevention
|
|
46
|
+
|
|
47
|
+
### Memory Providers (Testing)
|
|
48
|
+
|
|
49
|
+
- **MemoryStorageProvider** - In-memory storage
|
|
50
|
+
- **MemoryNonceCacheProvider** - In-memory nonce cache
|
|
51
|
+
- **MemoryIdentityProvider** - In-memory identity storage
|
|
52
|
+
- **MemoryStatusListStorage** - In-memory status list storage
|
|
53
|
+
- **MemoryDelegationGraphStorage** - In-memory delegation graph
|
|
54
|
+
|
|
55
|
+
### Utilities
|
|
56
|
+
|
|
57
|
+
- **SchemaVerifier** - JSON Schema draft-07 compliance verification
|
|
58
|
+
- **BitstringManager** - StatusList2021 bitstring operations
|
|
59
|
+
- **UserDidManager** - User DID generation and management
|
|
60
|
+
- **createDidKeyResolver** - did:key resolution utilities
|
|
61
|
+
|
|
62
|
+
### Error Types
|
|
63
|
+
|
|
64
|
+
- **DelegationRequiredError** - Thrown when delegation is required
|
|
65
|
+
- **OAuthRequiredError** - Thrown when OAuth authorization is needed
|
|
66
|
+
- **ProofVerificationError** - Proof verification failures
|
|
67
|
+
|
|
68
|
+
## Usage Examples
|
|
69
|
+
|
|
70
|
+
See the main [README.md](../README.md) for usage examples and the [TypeScript definitions](../src/index.ts) for complete type signatures.
|
|
71
|
+
|
|
72
|
+
## Related Documentation
|
|
73
|
+
|
|
74
|
+
- [W3C VC Delegation Guide](./W3C_VC_DELEGATION_GUIDE.md)
|
|
75
|
+
- [StatusList2021 Guide](./STATUSLIST2021_GUIDE.md)
|
|
76
|
+
- [Compliance Matrix](./COMPLIANCE_MATRIX.md)
|