@evomap/gep-mcp-server 1.0.0 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evomap/gep-mcp-server",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "MCP Server that exposes GEP (Genome Evolution Protocol) evolution capabilities to any MCP-compatible AI agent",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
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.0' },
26
+ { name: 'gep-mcp-server', version: '1.0.1' },
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 specPath = resolve(__dirname, '../../gep-protocol/spec/gep-spec-v1.md');
255
- const content = existsSync(specPath) ? readFileSync(specPath, 'utf8') : 'GEP spec not found at ' + specPath;
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
@@ -189,6 +189,11 @@ export class GepRuntime {
189
189
  }
190
190
 
191
191
  exportEvolution({ outputPath, agentName }) {
192
+ const resolvedOutput = resolve(outputPath);
193
+ const allowedRoots = [resolve(this.assetsDir), resolve(this.memoryDir, '..')];
194
+ if (!allowedRoots.some(root => resolvedOutput.startsWith(root + '/'))) {
195
+ outputPath = join(this.assetsDir, 'export.gepx');
196
+ }
192
197
  const tmpDir = `${outputPath}.tmp`;
193
198
  mkdirSync(join(tmpDir, 'genes'), { recursive: true });
194
199
  mkdirSync(join(tmpDir, 'capsules'), { recursive: true });
@@ -216,7 +221,12 @@ export class GepRuntime {
216
221
  };
217
222
  writeFileSync(join(tmpDir, 'manifest.json'), JSON.stringify(manifest, null, 2));
218
223
 
219
- execFileSync('tar', ['-czf', outputPath, '-C', tmpDir, '.'], { timeout: 30000 });
224
+ try {
225
+ execFileSync('tar', ['-czf', outputPath, '-C', tmpDir, '.'], { timeout: 30000 });
226
+ } catch (err) {
227
+ rmSync(tmpDir, { recursive: true, force: true });
228
+ return { ok: false, error: `tar failed: ${err.message}. Ensure tar is available on your system.` };
229
+ }
220
230
  rmSync(tmpDir, { recursive: true, force: true });
221
231
 
222
232
  return { ok: true, outputPath, manifest };
@@ -376,6 +386,19 @@ export class GepRuntime {
376
386
  _appendToGraph(event) {
377
387
  mkdirSync(this.memoryDir, { recursive: true });
378
388
  appendFileSync(this.memoryGraphPath, JSON.stringify(event) + '\n', 'utf8');
389
+ this._maybeTruncateGraph();
390
+ }
391
+
392
+ _maybeTruncateGraph() {
393
+ const MAX_ENTRIES = 5000;
394
+ try {
395
+ if (!existsSync(this.memoryGraphPath)) return;
396
+ const raw = readFileSync(this.memoryGraphPath, 'utf8');
397
+ const lines = raw.split('\n').filter(l => l.trim());
398
+ if (lines.length <= MAX_ENTRIES) return;
399
+ const kept = lines.slice(lines.length - MAX_ENTRIES);
400
+ writeFileSync(this.memoryGraphPath, kept.join('\n') + '\n', 'utf8');
401
+ } catch { /* best effort */ }
379
402
  }
380
403
 
381
404
  _recordToGraph({ kind, signals, gene, mutation }) {