@kya-os/mcp-i 1.2.11 → 1.3.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.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Node.js Provider Implementations
3
+ *
4
+ * Wraps existing Node.js implementations to work with the provider-based core.
5
+ * This maintains backward compatibility while enabling the new architecture.
6
+ */
7
+ import { CryptoProvider, ClockProvider, FetchProvider, StorageProvider, NonceCacheProvider, IdentityProvider, type AgentIdentity } from '@kya-os/mcp-i-core';
8
+ /**
9
+ * Node.js Crypto Provider using built-in crypto module
10
+ */
11
+ export declare class NodeCryptoProvider extends CryptoProvider {
12
+ sign(data: Uint8Array, privateKeyBase64: string): Promise<Uint8Array>;
13
+ verify(data: Uint8Array, signature: Uint8Array, publicKeyBase64: string): Promise<boolean>;
14
+ generateKeyPair(): Promise<{
15
+ privateKey: string;
16
+ publicKey: string;
17
+ }>;
18
+ hash(data: Uint8Array): Promise<Uint8Array>;
19
+ randomBytes(length: number): Promise<Uint8Array>;
20
+ }
21
+ /**
22
+ * Node.js Clock Provider
23
+ */
24
+ export declare class NodeClockProvider extends ClockProvider {
25
+ now(): number;
26
+ isWithinSkew(timestamp: number, skewSeconds: number): boolean;
27
+ hasExpired(expiresAt: number): boolean;
28
+ calculateExpiry(ttlSeconds: number): number;
29
+ format(timestamp: number): string;
30
+ }
31
+ /**
32
+ * Node.js Fetch Provider using axios
33
+ */
34
+ export declare class NodeFetchProvider extends FetchProvider {
35
+ resolveDID(did: string): Promise<any>;
36
+ fetchStatusList(url: string): Promise<any>;
37
+ fetchDelegationChain(id: string): Promise<any[]>;
38
+ fetch(url: string, options?: any): Promise<Response>;
39
+ }
40
+ /**
41
+ * File System Storage Provider
42
+ */
43
+ export declare class FileStorageProvider extends StorageProvider {
44
+ private basePath;
45
+ constructor(basePath: string);
46
+ get(key: string): Promise<string | null>;
47
+ set(key: string, value: string): Promise<void>;
48
+ delete(key: string): Promise<void>;
49
+ exists(key: string): Promise<boolean>;
50
+ list(prefix?: string): Promise<string[]>;
51
+ }
52
+ /**
53
+ * File System Identity Provider
54
+ */
55
+ export declare class FileIdentityProvider extends IdentityProvider {
56
+ private basePath;
57
+ private cryptoProvider;
58
+ private identityFile;
59
+ constructor(basePath: string, cryptoProvider: CryptoProvider);
60
+ getIdentity(): Promise<AgentIdentity>;
61
+ saveIdentity(identity: AgentIdentity): Promise<void>;
62
+ rotateKeys(): Promise<AgentIdentity>;
63
+ deleteIdentity(): Promise<void>;
64
+ private generateDIDFromPublicKey;
65
+ }
66
+ /**
67
+ * Get nonce cache provider based on environment
68
+ */
69
+ export declare function getNonceCacheProvider(): NonceCacheProvider;
@@ -0,0 +1,368 @@
1
+ "use strict";
2
+ /**
3
+ * Node.js Provider Implementations
4
+ *
5
+ * Wraps existing Node.js implementations to work with the provider-based core.
6
+ * This maintains backward compatibility while enabling the new architecture.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.FileIdentityProvider = exports.FileStorageProvider = exports.NodeFetchProvider = exports.NodeClockProvider = exports.NodeCryptoProvider = void 0;
46
+ exports.getNonceCacheProvider = getNonceCacheProvider;
47
+ const crypto = __importStar(require("crypto"));
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const axios_1 = __importDefault(require("axios"));
51
+ const mcp_i_core_1 = require("@kya-os/mcp-i-core");
52
+ /**
53
+ * Node.js Crypto Provider using built-in crypto module
54
+ */
55
+ class NodeCryptoProvider extends mcp_i_core_1.CryptoProvider {
56
+ async sign(data, privateKeyBase64) {
57
+ const privateKey = Buffer.from(privateKeyBase64, 'base64');
58
+ // Handle both raw 32-byte and full 64-byte Ed25519 keys
59
+ const keyBytes = privateKey.length === 64 ? privateKey.subarray(0, 32) : privateKey;
60
+ // Wrap in PKCS8 format for Node.js crypto
61
+ const pkcs8 = Buffer.concat([
62
+ Buffer.from('302e020100300506032b657004220420', 'hex'),
63
+ keyBytes
64
+ ]);
65
+ const keyObject = crypto.createPrivateKey({
66
+ key: pkcs8,
67
+ format: 'der',
68
+ type: 'pkcs8'
69
+ });
70
+ const signature = crypto.sign(null, Buffer.from(data), keyObject);
71
+ return new Uint8Array(signature);
72
+ }
73
+ async verify(data, signature, publicKeyBase64) {
74
+ try {
75
+ const publicKey = Buffer.from(publicKeyBase64, 'base64');
76
+ // Wrap in SPKI format for Node.js crypto
77
+ const spki = Buffer.concat([
78
+ Buffer.from('302a300506032b6570032100', 'hex'),
79
+ publicKey
80
+ ]);
81
+ const keyObject = crypto.createPublicKey({
82
+ key: spki,
83
+ format: 'der',
84
+ type: 'spki'
85
+ });
86
+ return crypto.verify(null, Buffer.from(data), keyObject, Buffer.from(signature));
87
+ }
88
+ catch {
89
+ return false;
90
+ }
91
+ }
92
+ async generateKeyPair() {
93
+ const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519', {
94
+ publicKeyEncoding: { type: 'spki', format: 'der' },
95
+ privateKeyEncoding: { type: 'pkcs8', format: 'der' }
96
+ });
97
+ // Extract raw keys from DER encoding
98
+ const rawPrivate = privateKey.subarray(16, 48);
99
+ const rawPublic = publicKey.subarray(12, 44);
100
+ return {
101
+ privateKey: rawPrivate.toString('base64'),
102
+ publicKey: rawPublic.toString('base64')
103
+ };
104
+ }
105
+ async hash(data) {
106
+ const hash = crypto.createHash('sha256').update(Buffer.from(data)).digest();
107
+ return new Uint8Array(hash);
108
+ }
109
+ async randomBytes(length) {
110
+ return new Uint8Array(crypto.randomBytes(length));
111
+ }
112
+ }
113
+ exports.NodeCryptoProvider = NodeCryptoProvider;
114
+ /**
115
+ * Node.js Clock Provider
116
+ */
117
+ class NodeClockProvider extends mcp_i_core_1.ClockProvider {
118
+ now() {
119
+ return Date.now();
120
+ }
121
+ isWithinSkew(timestamp, skewSeconds) {
122
+ const now = this.now();
123
+ const skewMs = skewSeconds * 1000;
124
+ return Math.abs(now - timestamp) <= skewMs;
125
+ }
126
+ hasExpired(expiresAt) {
127
+ return this.now() > expiresAt;
128
+ }
129
+ calculateExpiry(ttlSeconds) {
130
+ return this.now() + (ttlSeconds * 1000);
131
+ }
132
+ format(timestamp) {
133
+ return new Date(timestamp).toISOString();
134
+ }
135
+ }
136
+ exports.NodeClockProvider = NodeClockProvider;
137
+ /**
138
+ * Node.js Fetch Provider using axios
139
+ */
140
+ class NodeFetchProvider extends mcp_i_core_1.FetchProvider {
141
+ async resolveDID(did) {
142
+ if (did.startsWith('did:key:')) {
143
+ const publicKeyMultibase = did.slice('did:key:'.length);
144
+ return {
145
+ '@context': ['https://www.w3.org/ns/did/v1'],
146
+ id: did,
147
+ verificationMethod: [{
148
+ id: `${did}#key-1`,
149
+ type: 'Ed25519VerificationKey2020',
150
+ controller: did,
151
+ publicKeyMultibase
152
+ }],
153
+ authentication: [`${did}#key-1`],
154
+ assertionMethod: [`${did}#key-1`]
155
+ };
156
+ }
157
+ if (did.startsWith('did:web:')) {
158
+ const domain = did.slice('did:web:'.length).replace(/:/g, '/');
159
+ const url = `https://${domain}/.well-known/did.json`;
160
+ const response = await axios_1.default.get(url);
161
+ return response.data;
162
+ }
163
+ throw new Error(`Unsupported DID method: ${did}`);
164
+ }
165
+ async fetchStatusList(url) {
166
+ const response = await axios_1.default.get(url);
167
+ return response.data;
168
+ }
169
+ async fetchDelegationChain(id) {
170
+ // Would fetch from a delegation registry
171
+ return [];
172
+ }
173
+ async fetch(url, options) {
174
+ const response = await (0, axios_1.default)({
175
+ url,
176
+ method: options?.method || 'GET',
177
+ headers: options?.headers || {},
178
+ data: options?.body
179
+ });
180
+ // Create a Response-like object
181
+ return {
182
+ ok: response.status >= 200 && response.status < 300,
183
+ status: response.status,
184
+ statusText: response.statusText,
185
+ headers: new Headers(response.headers),
186
+ json: async () => response.data,
187
+ text: async () => JSON.stringify(response.data),
188
+ blob: async () => new Blob([JSON.stringify(response.data)]),
189
+ arrayBuffer: async () => {
190
+ const encoder = new TextEncoder();
191
+ return encoder.encode(JSON.stringify(response.data)).buffer;
192
+ },
193
+ bytes: async () => {
194
+ const encoder = new TextEncoder();
195
+ return encoder.encode(JSON.stringify(response.data));
196
+ },
197
+ formData: async () => { throw new Error('Not implemented'); },
198
+ clone: () => { throw new Error('Not implemented'); },
199
+ body: null,
200
+ bodyUsed: false,
201
+ redirected: false,
202
+ type: 'basic',
203
+ url
204
+ };
205
+ }
206
+ }
207
+ exports.NodeFetchProvider = NodeFetchProvider;
208
+ /**
209
+ * File System Storage Provider
210
+ */
211
+ class FileStorageProvider extends mcp_i_core_1.StorageProvider {
212
+ basePath;
213
+ constructor(basePath) {
214
+ super();
215
+ this.basePath = basePath;
216
+ fs.mkdirSync(basePath, { recursive: true });
217
+ }
218
+ async get(key) {
219
+ try {
220
+ const filePath = path.join(this.basePath, key);
221
+ return fs.readFileSync(filePath, 'utf-8');
222
+ }
223
+ catch {
224
+ return null;
225
+ }
226
+ }
227
+ async set(key, value) {
228
+ const filePath = path.join(this.basePath, key);
229
+ const dir = path.dirname(filePath);
230
+ fs.mkdirSync(dir, { recursive: true });
231
+ fs.writeFileSync(filePath, value);
232
+ }
233
+ async delete(key) {
234
+ try {
235
+ const filePath = path.join(this.basePath, key);
236
+ fs.unlinkSync(filePath);
237
+ }
238
+ catch {
239
+ // Ignore if file doesn't exist
240
+ }
241
+ }
242
+ async exists(key) {
243
+ const filePath = path.join(this.basePath, key);
244
+ return fs.existsSync(filePath);
245
+ }
246
+ async list(prefix) {
247
+ const files = [];
248
+ const basePath = this.basePath;
249
+ function walk(dir) {
250
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
251
+ for (const entry of entries) {
252
+ const fullPath = path.join(dir, entry.name);
253
+ if (entry.isDirectory()) {
254
+ walk(fullPath);
255
+ }
256
+ else {
257
+ const relativePath = path.relative(basePath, fullPath);
258
+ if (!prefix || relativePath.startsWith(prefix)) {
259
+ files.push(relativePath);
260
+ }
261
+ }
262
+ }
263
+ }
264
+ walk(this.basePath);
265
+ return files;
266
+ }
267
+ }
268
+ exports.FileStorageProvider = FileStorageProvider;
269
+ /**
270
+ * File System Identity Provider
271
+ */
272
+ class FileIdentityProvider extends mcp_i_core_1.IdentityProvider {
273
+ basePath;
274
+ cryptoProvider;
275
+ identityFile;
276
+ constructor(basePath, cryptoProvider) {
277
+ super();
278
+ this.basePath = basePath;
279
+ this.cryptoProvider = cryptoProvider;
280
+ this.identityFile = path.join(basePath, 'identity.json');
281
+ fs.mkdirSync(basePath, { recursive: true });
282
+ }
283
+ async getIdentity() {
284
+ // Try to load from environment first
285
+ if (process.env.MCP_IDENTITY_PRIVATE_KEY &&
286
+ process.env.MCP_IDENTITY_PUBLIC_KEY &&
287
+ process.env.MCP_IDENTITY_AGENT_DID) {
288
+ return {
289
+ did: process.env.MCP_IDENTITY_AGENT_DID,
290
+ keyId: `${process.env.MCP_IDENTITY_AGENT_DID}#key-1`,
291
+ privateKey: process.env.MCP_IDENTITY_PRIVATE_KEY,
292
+ publicKey: process.env.MCP_IDENTITY_PUBLIC_KEY,
293
+ createdAt: new Date().toISOString(),
294
+ type: 'production'
295
+ };
296
+ }
297
+ // Try to load from file
298
+ if (fs.existsSync(this.identityFile)) {
299
+ const data = fs.readFileSync(this.identityFile, 'utf-8');
300
+ return JSON.parse(data);
301
+ }
302
+ // Generate new identity
303
+ const keyPair = await this.cryptoProvider.generateKeyPair();
304
+ const did = this.generateDIDFromPublicKey(keyPair.publicKey);
305
+ const identity = {
306
+ did,
307
+ keyId: `${did}#key-1`,
308
+ privateKey: keyPair.privateKey,
309
+ publicKey: keyPair.publicKey,
310
+ createdAt: new Date().toISOString(),
311
+ type: 'development'
312
+ };
313
+ await this.saveIdentity(identity);
314
+ return identity;
315
+ }
316
+ async saveIdentity(identity) {
317
+ fs.writeFileSync(this.identityFile, JSON.stringify(identity, null, 2));
318
+ }
319
+ async rotateKeys() {
320
+ const keyPair = await this.cryptoProvider.generateKeyPair();
321
+ const did = this.generateDIDFromPublicKey(keyPair.publicKey);
322
+ const identity = {
323
+ did,
324
+ keyId: `${did}#key-1`,
325
+ privateKey: keyPair.privateKey,
326
+ publicKey: keyPair.publicKey,
327
+ createdAt: new Date().toISOString(),
328
+ type: 'development'
329
+ };
330
+ await this.saveIdentity(identity);
331
+ return identity;
332
+ }
333
+ async deleteIdentity() {
334
+ try {
335
+ fs.unlinkSync(this.identityFile);
336
+ }
337
+ catch {
338
+ // Ignore if file doesn't exist
339
+ }
340
+ }
341
+ generateDIDFromPublicKey(publicKey) {
342
+ const keyHash = Buffer.from(publicKey, 'base64')
343
+ .toString('base64url')
344
+ .substring(0, 32);
345
+ return `did:key:z${keyHash}`;
346
+ }
347
+ }
348
+ exports.FileIdentityProvider = FileIdentityProvider;
349
+ /**
350
+ * Get nonce cache provider based on environment
351
+ */
352
+ function getNonceCacheProvider() {
353
+ const cacheType = process.env.MCPI_NONCE_CACHE_TYPE ||
354
+ process.env.XMCPI_NONCE_CACHE_TYPE ||
355
+ 'memory';
356
+ switch (cacheType) {
357
+ case 'redis':
358
+ // TODO: Add Redis support
359
+ console.warn('Redis cache not yet supported in this version, falling back to memory');
360
+ return new mcp_i_core_1.MemoryNonceCacheProvider();
361
+ case 'dynamodb':
362
+ // TODO: Add DynamoDB support
363
+ console.warn('DynamoDB cache not yet supported in this version, falling back to memory');
364
+ return new mcp_i_core_1.MemoryNonceCacheProvider();
365
+ default:
366
+ return new mcp_i_core_1.MemoryNonceCacheProvider();
367
+ }
368
+ }