@evomap/gep-mcp-server 1.0.0 → 1.0.2
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/package.json +1 -1
- package/src/index.js +10 -4
- package/src/runtime.js +45 -9
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -23,7 +23,7 @@ const HUB_URL = process.env.EVOMAP_HUB_URL || 'https://evomap.ai';
|
|
|
23
23
|
const runtime = new GepRuntime({ assetsDir: ASSETS_DIR, memoryDir: MEMORY_DIR });
|
|
24
24
|
|
|
25
25
|
const server = new Server(
|
|
26
|
-
{ name: 'gep-mcp-server', version: '1.0.
|
|
26
|
+
{ name: 'gep-mcp-server', version: '1.0.2' },
|
|
27
27
|
{ capabilities: { tools: {}, resources: {} } }
|
|
28
28
|
);
|
|
29
29
|
|
|
@@ -208,7 +208,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
208
208
|
params.set('q', args.query.trim().slice(0, 500));
|
|
209
209
|
if (args.type && ['Gene', 'Capsule'].includes(args.type)) params.set('type', args.type);
|
|
210
210
|
if (args.outcome && ['success', 'failed'].includes(args.outcome)) params.set('outcome', args.outcome);
|
|
211
|
-
params.set('limit', String(args.limit || 10));
|
|
211
|
+
params.set('limit', String(Math.min(Math.max(1, parseInt(args.limit, 10) || 10), 50)));
|
|
212
212
|
params.set('include_context', 'true');
|
|
213
213
|
const url = `${HUB_URL}/a2a/assets/semantic-search?${params.toString()}`;
|
|
214
214
|
const res = await fetch(url, { signal: AbortSignal.timeout(15000) });
|
|
@@ -251,8 +251,14 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
251
251
|
const { uri } = request.params;
|
|
252
252
|
switch (uri) {
|
|
253
253
|
case 'gep://spec': {
|
|
254
|
-
const
|
|
255
|
-
|
|
254
|
+
const candidates = [
|
|
255
|
+
resolve(ASSETS_DIR, 'gep-spec-v1.md'),
|
|
256
|
+
resolve(__dirname, '../../gep-protocol/spec/gep-spec-v1.md'),
|
|
257
|
+
];
|
|
258
|
+
const specPath = candidates.find(p => existsSync(p));
|
|
259
|
+
const content = specPath
|
|
260
|
+
? readFileSync(specPath, 'utf8')
|
|
261
|
+
: 'GEP spec not found. Place gep-spec-v1.md in your GEP_ASSETS_DIR or install gep-protocol alongside this package.';
|
|
256
262
|
return { contents: [{ uri, mimeType: 'text/markdown', text: content }] };
|
|
257
263
|
}
|
|
258
264
|
case 'gep://genes':
|
package/src/runtime.js
CHANGED
|
@@ -16,7 +16,8 @@ export class GepRuntime {
|
|
|
16
16
|
this.store.ensureFiles();
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
evolve(
|
|
19
|
+
evolve(args) {
|
|
20
|
+
const { context, intent } = args || {};
|
|
20
21
|
const signals = this._extractSignals(context);
|
|
21
22
|
|
|
22
23
|
if (intent) {
|
|
@@ -96,7 +97,8 @@ export class GepRuntime {
|
|
|
96
97
|
};
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
recall(
|
|
100
|
+
recall(args) {
|
|
101
|
+
const { query, signals } = args || {};
|
|
100
102
|
const events = this._readGraphEvents(500);
|
|
101
103
|
const querySignals = signals || this._extractSignals(query);
|
|
102
104
|
const queryKey = this._computeSignalKey(querySignals);
|
|
@@ -130,7 +132,8 @@ export class GepRuntime {
|
|
|
130
132
|
};
|
|
131
133
|
}
|
|
132
134
|
|
|
133
|
-
recordOutcome(
|
|
135
|
+
recordOutcome(args) {
|
|
136
|
+
const { geneId, signals, status, score, summary } = args || {};
|
|
134
137
|
const signalKey = this._computeSignalKey(signals);
|
|
135
138
|
const ev = {
|
|
136
139
|
type: 'MemoryGraphEvent',
|
|
@@ -178,7 +181,8 @@ export class GepRuntime {
|
|
|
178
181
|
};
|
|
179
182
|
}
|
|
180
183
|
|
|
181
|
-
installGene(
|
|
184
|
+
installGene(args) {
|
|
185
|
+
const { gene } = args || {};
|
|
182
186
|
if (!gene || gene.type !== 'Gene' || !gene.id) {
|
|
183
187
|
return { ok: false, error: 'Invalid gene: must have type="Gene" and a non-empty id' };
|
|
184
188
|
}
|
|
@@ -188,7 +192,13 @@ export class GepRuntime {
|
|
|
188
192
|
return { ok: true, installed: gene.id };
|
|
189
193
|
}
|
|
190
194
|
|
|
191
|
-
exportEvolution(
|
|
195
|
+
exportEvolution(args) {
|
|
196
|
+
let { outputPath, agentName } = args || {};
|
|
197
|
+
const resolvedOutput = resolve(outputPath);
|
|
198
|
+
const allowedRoots = [resolve(this.assetsDir), resolve(this.memoryDir, '..')];
|
|
199
|
+
if (!allowedRoots.some(root => resolvedOutput.startsWith(root + '/'))) {
|
|
200
|
+
outputPath = join(this.assetsDir, 'export.gepx');
|
|
201
|
+
}
|
|
192
202
|
const tmpDir = `${outputPath}.tmp`;
|
|
193
203
|
mkdirSync(join(tmpDir, 'genes'), { recursive: true });
|
|
194
204
|
mkdirSync(join(tmpDir, 'capsules'), { recursive: true });
|
|
@@ -212,11 +222,16 @@ export class GepRuntime {
|
|
|
212
222
|
created_at: new Date().toISOString(),
|
|
213
223
|
agent_name: agentName || 'unknown',
|
|
214
224
|
statistics: this.getStatus().statistics,
|
|
215
|
-
source: { platform: 'gep-mcp-server', version: '1.0.
|
|
225
|
+
source: { platform: 'gep-mcp-server', version: '1.0.2' },
|
|
216
226
|
};
|
|
217
227
|
writeFileSync(join(tmpDir, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
|
218
228
|
|
|
219
|
-
|
|
229
|
+
try {
|
|
230
|
+
execFileSync('tar', ['-czf', outputPath, '-C', tmpDir, '.'], { timeout: 30000 });
|
|
231
|
+
} catch (err) {
|
|
232
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
233
|
+
return { ok: false, error: `tar failed: ${err.message}. Ensure tar is available on your system.` };
|
|
234
|
+
}
|
|
220
235
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
221
236
|
|
|
222
237
|
return { ok: true, outputPath, manifest };
|
|
@@ -226,7 +241,7 @@ export class GepRuntime {
|
|
|
226
241
|
const genes = this.store.loadGenes();
|
|
227
242
|
const capsules = this.store.loadCapsules();
|
|
228
243
|
const events = this.store.readAllEvents();
|
|
229
|
-
const
|
|
244
|
+
const graphEntryCount = this._countGraphEntries();
|
|
230
245
|
|
|
231
246
|
const recentEvents = events.slice(-5).map(e => ({
|
|
232
247
|
id: e.id,
|
|
@@ -243,7 +258,7 @@ export class GepRuntime {
|
|
|
243
258
|
total_genes: genes.length,
|
|
244
259
|
total_capsules: capsules.length,
|
|
245
260
|
total_events: events.length,
|
|
246
|
-
memory_graph_entries:
|
|
261
|
+
memory_graph_entries: graphEntryCount,
|
|
247
262
|
success_rate: events.length > 0 ? Math.round((successCount / events.length) * 100) / 100 : 0,
|
|
248
263
|
},
|
|
249
264
|
recent_events: recentEvents,
|
|
@@ -362,6 +377,14 @@ export class GepRuntime {
|
|
|
362
377
|
return 'improve success rate and efficiency';
|
|
363
378
|
}
|
|
364
379
|
|
|
380
|
+
_countGraphEntries() {
|
|
381
|
+
try {
|
|
382
|
+
if (!existsSync(this.memoryGraphPath)) return 0;
|
|
383
|
+
const raw = readFileSync(this.memoryGraphPath, 'utf8');
|
|
384
|
+
return raw.split('\n').filter(l => l.trim()).length;
|
|
385
|
+
} catch { return 0; }
|
|
386
|
+
}
|
|
387
|
+
|
|
365
388
|
_readGraphEvents(limit = 1000) {
|
|
366
389
|
try {
|
|
367
390
|
if (!existsSync(this.memoryGraphPath)) return [];
|
|
@@ -376,6 +399,19 @@ export class GepRuntime {
|
|
|
376
399
|
_appendToGraph(event) {
|
|
377
400
|
mkdirSync(this.memoryDir, { recursive: true });
|
|
378
401
|
appendFileSync(this.memoryGraphPath, JSON.stringify(event) + '\n', 'utf8');
|
|
402
|
+
this._maybeTruncateGraph();
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
_maybeTruncateGraph() {
|
|
406
|
+
const MAX_ENTRIES = 5000;
|
|
407
|
+
try {
|
|
408
|
+
if (!existsSync(this.memoryGraphPath)) return;
|
|
409
|
+
const raw = readFileSync(this.memoryGraphPath, 'utf8');
|
|
410
|
+
const lines = raw.split('\n').filter(l => l.trim());
|
|
411
|
+
if (lines.length <= MAX_ENTRIES) return;
|
|
412
|
+
const kept = lines.slice(lines.length - MAX_ENTRIES);
|
|
413
|
+
writeFileSync(this.memoryGraphPath, kept.join('\n') + '\n', 'utf8');
|
|
414
|
+
} catch { /* best effort */ }
|
|
379
415
|
}
|
|
380
416
|
|
|
381
417
|
_recordToGraph({ kind, signals, gene, mutation }) {
|