genesis-ai-cli 7.4.8 → 7.5.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.
- package/dist/src/mcp/cache.d.ts +100 -0
- package/dist/src/mcp/cache.js +395 -0
- package/dist/src/mcp/index.d.ts +15 -1
- package/dist/src/mcp/index.js +16 -1
- package/dist/src/mcp/multimodal.d.ts +52 -0
- package/dist/src/mcp/multimodal.js +355 -0
- package/dist/src/mcp/parallel-executor.d.ts +113 -0
- package/dist/src/mcp/parallel-executor.js +335 -0
- package/dist/src/mcp/streaming.d.ts +78 -0
- package/dist/src/mcp/streaming.js +345 -0
- package/dist/src/mcp/tool-chain.d.ts +79 -0
- package/dist/src/mcp/tool-chain.js +330 -0
- package/dist/src/mcp/transformers.d.ts +156 -0
- package/dist/src/mcp/transformers.js +362 -0
- package/package.json +1 -1
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis MCP Intelligent Cache
|
|
3
|
+
*
|
|
4
|
+
* Smart caching with per-server TTL, semantic deduplication,
|
|
5
|
+
* and LRU eviction.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Per-server TTL configuration
|
|
9
|
+
* - Semantic key hashing (similar queries hit same cache)
|
|
10
|
+
* - LRU eviction with configurable max size
|
|
11
|
+
* - Cache statistics and monitoring
|
|
12
|
+
* - Invalidation patterns
|
|
13
|
+
* - Persistent cache option (filesystem)
|
|
14
|
+
*/
|
|
15
|
+
import { MCPServerName } from '../types.js';
|
|
16
|
+
import { MCPCallResult } from './index.js';
|
|
17
|
+
export interface CacheEntry<T = any> {
|
|
18
|
+
key: string;
|
|
19
|
+
data: T;
|
|
20
|
+
server: MCPServerName;
|
|
21
|
+
tool: string;
|
|
22
|
+
createdAt: number;
|
|
23
|
+
expiresAt: number;
|
|
24
|
+
hits: number;
|
|
25
|
+
size: number;
|
|
26
|
+
}
|
|
27
|
+
export interface CacheStats {
|
|
28
|
+
hits: number;
|
|
29
|
+
misses: number;
|
|
30
|
+
entries: number;
|
|
31
|
+
totalSize: number;
|
|
32
|
+
hitRate: number;
|
|
33
|
+
byServer: Record<MCPServerName, {
|
|
34
|
+
hits: number;
|
|
35
|
+
misses: number;
|
|
36
|
+
entries: number;
|
|
37
|
+
}>;
|
|
38
|
+
}
|
|
39
|
+
export interface CacheConfig {
|
|
40
|
+
maxEntries?: number;
|
|
41
|
+
maxSize?: number;
|
|
42
|
+
defaultTTL?: number;
|
|
43
|
+
serverTTL?: Partial<Record<MCPServerName, number>>;
|
|
44
|
+
persistent?: boolean;
|
|
45
|
+
persistPath?: string;
|
|
46
|
+
semanticKeys?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export declare class MCPCache {
|
|
49
|
+
private cache;
|
|
50
|
+
private accessOrder;
|
|
51
|
+
private stats;
|
|
52
|
+
private config;
|
|
53
|
+
constructor(config?: CacheConfig);
|
|
54
|
+
/**
|
|
55
|
+
* Get cached result
|
|
56
|
+
*/
|
|
57
|
+
get<T = any>(server: MCPServerName, tool: string, params: Record<string, any>): CacheEntry<T> | null;
|
|
58
|
+
/**
|
|
59
|
+
* Cache a result
|
|
60
|
+
*/
|
|
61
|
+
set<T = any>(server: MCPServerName, tool: string, params: Record<string, any>, data: T): void;
|
|
62
|
+
/**
|
|
63
|
+
* Wrap an MCP call with caching
|
|
64
|
+
*/
|
|
65
|
+
wrap<T = any>(server: MCPServerName, tool: string, params: Record<string, any>, fetcher: () => Promise<MCPCallResult<T>>): Promise<MCPCallResult<T>>;
|
|
66
|
+
/**
|
|
67
|
+
* Invalidate cache entries
|
|
68
|
+
*/
|
|
69
|
+
invalidate(pattern: {
|
|
70
|
+
server?: MCPServerName;
|
|
71
|
+
tool?: string;
|
|
72
|
+
olderThan?: number;
|
|
73
|
+
}): number;
|
|
74
|
+
/**
|
|
75
|
+
* Clear entire cache
|
|
76
|
+
*/
|
|
77
|
+
clear(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Get cache statistics
|
|
80
|
+
*/
|
|
81
|
+
getStats(): CacheStats;
|
|
82
|
+
/**
|
|
83
|
+
* Get cache entries for debugging
|
|
84
|
+
*/
|
|
85
|
+
getEntries(): CacheEntry[];
|
|
86
|
+
private generateKey;
|
|
87
|
+
private normalizeParams;
|
|
88
|
+
private getTTL;
|
|
89
|
+
private estimateSize;
|
|
90
|
+
private updateAccessOrder;
|
|
91
|
+
private evictIfNeeded;
|
|
92
|
+
private delete;
|
|
93
|
+
private updateHitRate;
|
|
94
|
+
private loadFromDisk;
|
|
95
|
+
private persistEntry;
|
|
96
|
+
private clearDisk;
|
|
97
|
+
}
|
|
98
|
+
export declare function getMCPCache(config?: CacheConfig): MCPCache;
|
|
99
|
+
export declare function resetMCPCache(): void;
|
|
100
|
+
export declare function withCache<T = any>(server: MCPServerName, tool: string, params: Record<string, any>, fetcher: () => Promise<MCPCallResult<T>>): Promise<MCPCallResult<T>>;
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis MCP Intelligent Cache
|
|
4
|
+
*
|
|
5
|
+
* Smart caching with per-server TTL, semantic deduplication,
|
|
6
|
+
* and LRU eviction.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Per-server TTL configuration
|
|
10
|
+
* - Semantic key hashing (similar queries hit same cache)
|
|
11
|
+
* - LRU eviction with configurable max size
|
|
12
|
+
* - Cache statistics and monitoring
|
|
13
|
+
* - Invalidation patterns
|
|
14
|
+
* - Persistent cache option (filesystem)
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.MCPCache = void 0;
|
|
51
|
+
exports.getMCPCache = getMCPCache;
|
|
52
|
+
exports.resetMCPCache = resetMCPCache;
|
|
53
|
+
exports.withCache = withCache;
|
|
54
|
+
const crypto_1 = require("crypto");
|
|
55
|
+
const fs = __importStar(require("fs"));
|
|
56
|
+
const path = __importStar(require("path"));
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Default TTLs per server
|
|
59
|
+
// ============================================================================
|
|
60
|
+
const DEFAULT_SERVER_TTL = {
|
|
61
|
+
// Knowledge (can be cached longer)
|
|
62
|
+
'arxiv': 1000 * 60 * 60 * 24, // 24 hours
|
|
63
|
+
'semantic-scholar': 1000 * 60 * 60 * 24, // 24 hours
|
|
64
|
+
'context7': 1000 * 60 * 60 * 12, // 12 hours
|
|
65
|
+
'wolfram': 1000 * 60 * 60, // 1 hour
|
|
66
|
+
// Research (moderate caching)
|
|
67
|
+
'gemini': 1000 * 60 * 30, // 30 minutes
|
|
68
|
+
'brave-search': 1000 * 60 * 15, // 15 minutes (search results change)
|
|
69
|
+
'exa': 1000 * 60 * 30, // 30 minutes
|
|
70
|
+
'firecrawl': 1000 * 60 * 60, // 1 hour (scraped content)
|
|
71
|
+
// Creation (no caching by default)
|
|
72
|
+
'openai': 0, // Don't cache AI responses
|
|
73
|
+
'github': 1000 * 60 * 5, // 5 minutes (repos can change)
|
|
74
|
+
// Visual (no caching)
|
|
75
|
+
'stability-ai': 0, // Don't cache generated images
|
|
76
|
+
// Storage (short cache)
|
|
77
|
+
'memory': 1000 * 60 * 5, // 5 minutes
|
|
78
|
+
'filesystem': 1000 * 60, // 1 minute
|
|
79
|
+
};
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Cache Implementation
|
|
82
|
+
// ============================================================================
|
|
83
|
+
class MCPCache {
|
|
84
|
+
cache = new Map();
|
|
85
|
+
accessOrder = []; // For LRU
|
|
86
|
+
stats = {
|
|
87
|
+
hits: 0,
|
|
88
|
+
misses: 0,
|
|
89
|
+
entries: 0,
|
|
90
|
+
totalSize: 0,
|
|
91
|
+
hitRate: 0,
|
|
92
|
+
byServer: {},
|
|
93
|
+
};
|
|
94
|
+
config;
|
|
95
|
+
constructor(config = {}) {
|
|
96
|
+
this.config = {
|
|
97
|
+
maxEntries: config.maxEntries ?? 1000,
|
|
98
|
+
maxSize: config.maxSize ?? 50 * 1024 * 1024, // 50MB
|
|
99
|
+
defaultTTL: config.defaultTTL ?? 1000 * 60 * 30, // 30 minutes
|
|
100
|
+
serverTTL: { ...DEFAULT_SERVER_TTL, ...config.serverTTL },
|
|
101
|
+
persistent: config.persistent ?? false,
|
|
102
|
+
persistPath: config.persistPath ?? path.join(process.cwd(), '.genesis-cache'),
|
|
103
|
+
semanticKeys: config.semanticKeys ?? true,
|
|
104
|
+
};
|
|
105
|
+
// Load persistent cache
|
|
106
|
+
if (this.config.persistent) {
|
|
107
|
+
this.loadFromDisk();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get cached result
|
|
112
|
+
*/
|
|
113
|
+
get(server, tool, params) {
|
|
114
|
+
const key = this.generateKey(server, tool, params);
|
|
115
|
+
const entry = this.cache.get(key);
|
|
116
|
+
// Initialize server stats if needed
|
|
117
|
+
if (!this.stats.byServer[server]) {
|
|
118
|
+
this.stats.byServer[server] = { hits: 0, misses: 0, entries: 0 };
|
|
119
|
+
}
|
|
120
|
+
if (!entry) {
|
|
121
|
+
this.stats.misses++;
|
|
122
|
+
this.stats.byServer[server].misses++;
|
|
123
|
+
this.updateHitRate();
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
// Check expiration
|
|
127
|
+
if (Date.now() > entry.expiresAt) {
|
|
128
|
+
this.delete(key);
|
|
129
|
+
this.stats.misses++;
|
|
130
|
+
this.stats.byServer[server].misses++;
|
|
131
|
+
this.updateHitRate();
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
// Update LRU order
|
|
135
|
+
this.updateAccessOrder(key);
|
|
136
|
+
entry.hits++;
|
|
137
|
+
this.stats.hits++;
|
|
138
|
+
this.stats.byServer[server].hits++;
|
|
139
|
+
this.updateHitRate();
|
|
140
|
+
return entry;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Cache a result
|
|
144
|
+
*/
|
|
145
|
+
set(server, tool, params, data) {
|
|
146
|
+
const ttl = this.getTTL(server);
|
|
147
|
+
// Don't cache if TTL is 0
|
|
148
|
+
if (ttl === 0)
|
|
149
|
+
return;
|
|
150
|
+
const key = this.generateKey(server, tool, params);
|
|
151
|
+
const size = this.estimateSize(data);
|
|
152
|
+
// Evict if necessary
|
|
153
|
+
this.evictIfNeeded(size);
|
|
154
|
+
const entry = {
|
|
155
|
+
key,
|
|
156
|
+
data,
|
|
157
|
+
server,
|
|
158
|
+
tool,
|
|
159
|
+
createdAt: Date.now(),
|
|
160
|
+
expiresAt: Date.now() + ttl,
|
|
161
|
+
hits: 0,
|
|
162
|
+
size,
|
|
163
|
+
};
|
|
164
|
+
this.cache.set(key, entry);
|
|
165
|
+
this.updateAccessOrder(key);
|
|
166
|
+
// Update stats
|
|
167
|
+
this.stats.entries = this.cache.size;
|
|
168
|
+
this.stats.totalSize += size;
|
|
169
|
+
if (!this.stats.byServer[server]) {
|
|
170
|
+
this.stats.byServer[server] = { hits: 0, misses: 0, entries: 0 };
|
|
171
|
+
}
|
|
172
|
+
this.stats.byServer[server].entries++;
|
|
173
|
+
// Persist if enabled
|
|
174
|
+
if (this.config.persistent) {
|
|
175
|
+
this.persistEntry(entry);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Wrap an MCP call with caching
|
|
180
|
+
*/
|
|
181
|
+
async wrap(server, tool, params, fetcher) {
|
|
182
|
+
// Check cache first
|
|
183
|
+
const cached = this.get(server, tool, params);
|
|
184
|
+
if (cached) {
|
|
185
|
+
return {
|
|
186
|
+
success: true,
|
|
187
|
+
data: cached.data,
|
|
188
|
+
server,
|
|
189
|
+
tool,
|
|
190
|
+
mode: 'real',
|
|
191
|
+
latency: 0,
|
|
192
|
+
timestamp: new Date(),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
// Fetch and cache
|
|
196
|
+
const result = await fetcher();
|
|
197
|
+
if (result.success && result.data) {
|
|
198
|
+
this.set(server, tool, params, result.data);
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Invalidate cache entries
|
|
204
|
+
*/
|
|
205
|
+
invalidate(pattern) {
|
|
206
|
+
let invalidated = 0;
|
|
207
|
+
const now = Date.now();
|
|
208
|
+
for (const [key, entry] of this.cache) {
|
|
209
|
+
let shouldInvalidate = false;
|
|
210
|
+
if (pattern.server && entry.server === pattern.server) {
|
|
211
|
+
shouldInvalidate = true;
|
|
212
|
+
}
|
|
213
|
+
if (pattern.tool && entry.tool === pattern.tool) {
|
|
214
|
+
shouldInvalidate = true;
|
|
215
|
+
}
|
|
216
|
+
if (pattern.olderThan && now - entry.createdAt > pattern.olderThan) {
|
|
217
|
+
shouldInvalidate = true;
|
|
218
|
+
}
|
|
219
|
+
if (shouldInvalidate) {
|
|
220
|
+
this.delete(key);
|
|
221
|
+
invalidated++;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return invalidated;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Clear entire cache
|
|
228
|
+
*/
|
|
229
|
+
clear() {
|
|
230
|
+
this.cache.clear();
|
|
231
|
+
this.accessOrder = [];
|
|
232
|
+
this.stats = {
|
|
233
|
+
hits: 0,
|
|
234
|
+
misses: 0,
|
|
235
|
+
entries: 0,
|
|
236
|
+
totalSize: 0,
|
|
237
|
+
hitRate: 0,
|
|
238
|
+
byServer: {},
|
|
239
|
+
};
|
|
240
|
+
if (this.config.persistent) {
|
|
241
|
+
this.clearDisk();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Get cache statistics
|
|
246
|
+
*/
|
|
247
|
+
getStats() {
|
|
248
|
+
return { ...this.stats };
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get cache entries for debugging
|
|
252
|
+
*/
|
|
253
|
+
getEntries() {
|
|
254
|
+
return Array.from(this.cache.values());
|
|
255
|
+
}
|
|
256
|
+
// ============================================================================
|
|
257
|
+
// Private Methods
|
|
258
|
+
// ============================================================================
|
|
259
|
+
generateKey(server, tool, params) {
|
|
260
|
+
let paramsStr = JSON.stringify(params, Object.keys(params).sort());
|
|
261
|
+
// Semantic key normalization
|
|
262
|
+
if (this.config.semanticKeys) {
|
|
263
|
+
paramsStr = this.normalizeParams(paramsStr);
|
|
264
|
+
}
|
|
265
|
+
const hash = (0, crypto_1.createHash)('sha256')
|
|
266
|
+
.update(`${server}:${tool}:${paramsStr}`)
|
|
267
|
+
.digest('hex')
|
|
268
|
+
.slice(0, 16);
|
|
269
|
+
return `${server}:${tool}:${hash}`;
|
|
270
|
+
}
|
|
271
|
+
normalizeParams(paramsStr) {
|
|
272
|
+
// Normalize whitespace and case for query-like params
|
|
273
|
+
return paramsStr
|
|
274
|
+
.toLowerCase()
|
|
275
|
+
.replace(/\s+/g, ' ')
|
|
276
|
+
.trim();
|
|
277
|
+
}
|
|
278
|
+
getTTL(server) {
|
|
279
|
+
return this.config.serverTTL[server] ?? this.config.defaultTTL;
|
|
280
|
+
}
|
|
281
|
+
estimateSize(data) {
|
|
282
|
+
try {
|
|
283
|
+
return JSON.stringify(data).length * 2; // Rough estimate for UTF-16
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return 1000; // Default estimate
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
updateAccessOrder(key) {
|
|
290
|
+
const index = this.accessOrder.indexOf(key);
|
|
291
|
+
if (index > -1) {
|
|
292
|
+
this.accessOrder.splice(index, 1);
|
|
293
|
+
}
|
|
294
|
+
this.accessOrder.push(key);
|
|
295
|
+
}
|
|
296
|
+
evictIfNeeded(newSize) {
|
|
297
|
+
// Evict by count
|
|
298
|
+
while (this.cache.size >= this.config.maxEntries && this.accessOrder.length > 0) {
|
|
299
|
+
const oldest = this.accessOrder.shift();
|
|
300
|
+
this.delete(oldest);
|
|
301
|
+
}
|
|
302
|
+
// Evict by size
|
|
303
|
+
while (this.stats.totalSize + newSize > this.config.maxSize && this.accessOrder.length > 0) {
|
|
304
|
+
const oldest = this.accessOrder.shift();
|
|
305
|
+
this.delete(oldest);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
delete(key) {
|
|
309
|
+
const entry = this.cache.get(key);
|
|
310
|
+
if (entry) {
|
|
311
|
+
this.stats.totalSize -= entry.size;
|
|
312
|
+
this.stats.entries--;
|
|
313
|
+
if (this.stats.byServer[entry.server]) {
|
|
314
|
+
this.stats.byServer[entry.server].entries--;
|
|
315
|
+
}
|
|
316
|
+
this.cache.delete(key);
|
|
317
|
+
const idx = this.accessOrder.indexOf(key);
|
|
318
|
+
if (idx > -1) {
|
|
319
|
+
this.accessOrder.splice(idx, 1);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
updateHitRate() {
|
|
324
|
+
const total = this.stats.hits + this.stats.misses;
|
|
325
|
+
this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
|
|
326
|
+
}
|
|
327
|
+
// ============================================================================
|
|
328
|
+
// Persistence
|
|
329
|
+
// ============================================================================
|
|
330
|
+
loadFromDisk() {
|
|
331
|
+
try {
|
|
332
|
+
const indexPath = path.join(this.config.persistPath, 'cache-index.json');
|
|
333
|
+
if (fs.existsSync(indexPath)) {
|
|
334
|
+
const index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
|
|
335
|
+
for (const entry of index.entries) {
|
|
336
|
+
if (Date.now() < entry.expiresAt) {
|
|
337
|
+
this.cache.set(entry.key, entry);
|
|
338
|
+
this.accessOrder.push(entry.key);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
this.stats.entries = this.cache.size;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
// Ignore load errors
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
persistEntry(entry) {
|
|
349
|
+
try {
|
|
350
|
+
if (!fs.existsSync(this.config.persistPath)) {
|
|
351
|
+
fs.mkdirSync(this.config.persistPath, { recursive: true });
|
|
352
|
+
}
|
|
353
|
+
const indexPath = path.join(this.config.persistPath, 'cache-index.json');
|
|
354
|
+
const index = { entries: Array.from(this.cache.values()) };
|
|
355
|
+
fs.writeFileSync(indexPath, JSON.stringify(index));
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
// Ignore persist errors
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
clearDisk() {
|
|
362
|
+
try {
|
|
363
|
+
const indexPath = path.join(this.config.persistPath, 'cache-index.json');
|
|
364
|
+
if (fs.existsSync(indexPath)) {
|
|
365
|
+
fs.unlinkSync(indexPath);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
// Ignore clear errors
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
exports.MCPCache = MCPCache;
|
|
374
|
+
// ============================================================================
|
|
375
|
+
// Singleton
|
|
376
|
+
// ============================================================================
|
|
377
|
+
let cacheInstance = null;
|
|
378
|
+
function getMCPCache(config) {
|
|
379
|
+
if (!cacheInstance) {
|
|
380
|
+
cacheInstance = new MCPCache(config);
|
|
381
|
+
}
|
|
382
|
+
return cacheInstance;
|
|
383
|
+
}
|
|
384
|
+
function resetMCPCache() {
|
|
385
|
+
if (cacheInstance) {
|
|
386
|
+
cacheInstance.clear();
|
|
387
|
+
}
|
|
388
|
+
cacheInstance = null;
|
|
389
|
+
}
|
|
390
|
+
// ============================================================================
|
|
391
|
+
// Decorator-style cache wrapper
|
|
392
|
+
// ============================================================================
|
|
393
|
+
function withCache(server, tool, params, fetcher) {
|
|
394
|
+
return getMCPCache().wrap(server, tool, params, fetcher);
|
|
395
|
+
}
|
package/dist/src/mcp/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Genesis
|
|
2
|
+
* Genesis 7.5 - Real MCP Client Module
|
|
3
3
|
*
|
|
4
4
|
* Connects to actual MCP servers using @modelcontextprotocol/sdk.
|
|
5
5
|
* Spawns servers on demand and manages connections.
|
|
@@ -8,8 +8,22 @@
|
|
|
8
8
|
* - GENESIS_MCP_MODE: 'real' | 'simulated' | 'hybrid' (default: 'simulated')
|
|
9
9
|
* - GENESIS_MCP_TIMEOUT: Timeout in ms (default: 30000)
|
|
10
10
|
* - GENESIS_MCP_LOG: Enable MCP call logging (default: false)
|
|
11
|
+
*
|
|
12
|
+
* New in 7.5: Frontier MCP capabilities
|
|
13
|
+
* - Tool Chaining: Automatic orchestration of dependent tool calls
|
|
14
|
+
* - Streaming: Real-time result streaming with progress
|
|
15
|
+
* - Multimodal: Image/media display in terminal
|
|
16
|
+
* - Cache: Intelligent per-server caching with TTL
|
|
17
|
+
* - DAG Executor: Parallel execution with dependency awareness
|
|
18
|
+
* - Transformers: Composable result transformations
|
|
11
19
|
*/
|
|
12
20
|
export * from './resilient.js';
|
|
21
|
+
export * from './tool-chain.js';
|
|
22
|
+
export * from './streaming.js';
|
|
23
|
+
export * from './multimodal.js';
|
|
24
|
+
export * from './cache.js';
|
|
25
|
+
export * from './parallel-executor.js';
|
|
26
|
+
export * from './transformers.js';
|
|
13
27
|
import { MCPServerName } from '../types.js';
|
|
14
28
|
export type MCPMode = 'real' | 'simulated' | 'hybrid';
|
|
15
29
|
export interface MCPCallOptions {
|
package/dist/src/mcp/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Genesis
|
|
3
|
+
* Genesis 7.5 - Real MCP Client Module
|
|
4
4
|
*
|
|
5
5
|
* Connects to actual MCP servers using @modelcontextprotocol/sdk.
|
|
6
6
|
* Spawns servers on demand and manages connections.
|
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
* - GENESIS_MCP_MODE: 'real' | 'simulated' | 'hybrid' (default: 'simulated')
|
|
10
10
|
* - GENESIS_MCP_TIMEOUT: Timeout in ms (default: 30000)
|
|
11
11
|
* - GENESIS_MCP_LOG: Enable MCP call logging (default: false)
|
|
12
|
+
*
|
|
13
|
+
* New in 7.5: Frontier MCP capabilities
|
|
14
|
+
* - Tool Chaining: Automatic orchestration of dependent tool calls
|
|
15
|
+
* - Streaming: Real-time result streaming with progress
|
|
16
|
+
* - Multimodal: Image/media display in terminal
|
|
17
|
+
* - Cache: Intelligent per-server caching with TTL
|
|
18
|
+
* - DAG Executor: Parallel execution with dependency awareness
|
|
19
|
+
* - Transformers: Composable result transformations
|
|
12
20
|
*/
|
|
13
21
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
22
|
if (k2 === undefined) k2 = k;
|
|
@@ -33,6 +41,13 @@ exports.isSimulatedResult = isSimulatedResult;
|
|
|
33
41
|
exports.logMCPMode = logMCPMode;
|
|
34
42
|
// Re-export Phase 8: Resilient MCP Wrapper
|
|
35
43
|
__exportStar(require("./resilient.js"), exports);
|
|
44
|
+
// Re-export Phase 10: Frontier MCP Capabilities
|
|
45
|
+
__exportStar(require("./tool-chain.js"), exports);
|
|
46
|
+
__exportStar(require("./streaming.js"), exports);
|
|
47
|
+
__exportStar(require("./multimodal.js"), exports);
|
|
48
|
+
__exportStar(require("./cache.js"), exports);
|
|
49
|
+
__exportStar(require("./parallel-executor.js"), exports);
|
|
50
|
+
__exportStar(require("./transformers.js"), exports);
|
|
36
51
|
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
37
52
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
38
53
|
const crypto_1 = require("crypto");
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis MCP Multimodal Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles image, audio, and other media types from MCP tool results.
|
|
5
|
+
* Provides terminal display, file management, and format conversion.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Detect media in tool results
|
|
9
|
+
* - Display images in terminal (iTerm2, Kitty, sixel)
|
|
10
|
+
* - Open media with system default apps
|
|
11
|
+
* - Convert between formats
|
|
12
|
+
* - Thumbnail generation
|
|
13
|
+
*/
|
|
14
|
+
export type MediaType = 'image' | 'audio' | 'video' | 'document' | 'unknown';
|
|
15
|
+
export interface MediaInfo {
|
|
16
|
+
type: MediaType;
|
|
17
|
+
mimeType: string;
|
|
18
|
+
path?: string;
|
|
19
|
+
url?: string;
|
|
20
|
+
base64?: string;
|
|
21
|
+
width?: number;
|
|
22
|
+
height?: number;
|
|
23
|
+
size?: number;
|
|
24
|
+
format?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface DisplayOptions {
|
|
27
|
+
maxWidth?: number;
|
|
28
|
+
maxHeight?: number;
|
|
29
|
+
autoOpen?: boolean;
|
|
30
|
+
inline?: boolean;
|
|
31
|
+
protocol?: TerminalProtocol;
|
|
32
|
+
}
|
|
33
|
+
export type TerminalProtocol = 'iterm2' | 'kitty' | 'sixel' | 'ascii' | 'none';
|
|
34
|
+
export interface MultimodalResult {
|
|
35
|
+
detected: boolean;
|
|
36
|
+
media: MediaInfo[];
|
|
37
|
+
displayedInline: boolean;
|
|
38
|
+
openedExternally: boolean;
|
|
39
|
+
}
|
|
40
|
+
export declare function detectMediaType(input: string | MediaInfo): MediaType;
|
|
41
|
+
export declare function extractMediaFromResult(result: any): MediaInfo[];
|
|
42
|
+
export declare function detectTerminalProtocol(): TerminalProtocol;
|
|
43
|
+
export declare function displayImageInline(imagePath: string, options?: DisplayOptions): Promise<boolean>;
|
|
44
|
+
export declare function openWithSystemViewer(filePath: string): Promise<boolean>;
|
|
45
|
+
export declare class MultimodalHandler {
|
|
46
|
+
private options;
|
|
47
|
+
constructor(options?: DisplayOptions);
|
|
48
|
+
handleResult(result: any): Promise<MultimodalResult>;
|
|
49
|
+
setOptions(options: Partial<DisplayOptions>): void;
|
|
50
|
+
}
|
|
51
|
+
export declare function getMultimodalHandler(options?: DisplayOptions): MultimodalHandler;
|
|
52
|
+
export declare function handleMultimodalResult(result: any): Promise<MultimodalResult>;
|