genesis-ai-cli 7.4.5
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/.env.example +78 -0
- package/README.md +282 -0
- package/dist/src/active-inference/actions.d.ts +75 -0
- package/dist/src/active-inference/actions.js +250 -0
- package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
- package/dist/src/active-inference/autonomous-loop.js +289 -0
- package/dist/src/active-inference/core.d.ts +85 -0
- package/dist/src/active-inference/core.js +555 -0
- package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
- package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
- package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
- package/dist/src/active-inference/demo-value-integration.js +174 -0
- package/dist/src/active-inference/index.d.ts +32 -0
- package/dist/src/active-inference/index.js +88 -0
- package/dist/src/active-inference/integration.d.ts +114 -0
- package/dist/src/active-inference/integration.js +698 -0
- package/dist/src/active-inference/memory-integration.d.ts +51 -0
- package/dist/src/active-inference/memory-integration.js +232 -0
- package/dist/src/active-inference/observations.d.ts +67 -0
- package/dist/src/active-inference/observations.js +147 -0
- package/dist/src/active-inference/test-active-inference.d.ts +8 -0
- package/dist/src/active-inference/test-active-inference.js +320 -0
- package/dist/src/active-inference/test-value-integration.d.ts +6 -0
- package/dist/src/active-inference/test-value-integration.js +168 -0
- package/dist/src/active-inference/types.d.ts +150 -0
- package/dist/src/active-inference/types.js +59 -0
- package/dist/src/active-inference/value-integration.d.ts +164 -0
- package/dist/src/active-inference/value-integration.js +459 -0
- package/dist/src/agents/base-agent.d.ts +53 -0
- package/dist/src/agents/base-agent.js +178 -0
- package/dist/src/agents/builder.d.ts +67 -0
- package/dist/src/agents/builder.js +537 -0
- package/dist/src/agents/critic.d.ts +35 -0
- package/dist/src/agents/critic.js +322 -0
- package/dist/src/agents/ethicist.d.ts +54 -0
- package/dist/src/agents/ethicist.js +393 -0
- package/dist/src/agents/explorer.d.ts +26 -0
- package/dist/src/agents/explorer.js +216 -0
- package/dist/src/agents/feeling.d.ts +41 -0
- package/dist/src/agents/feeling.js +320 -0
- package/dist/src/agents/index.d.ts +111 -0
- package/dist/src/agents/index.js +222 -0
- package/dist/src/agents/memory.d.ts +69 -0
- package/dist/src/agents/memory.js +404 -0
- package/dist/src/agents/message-bus.d.ts +88 -0
- package/dist/src/agents/message-bus.js +267 -0
- package/dist/src/agents/narrator.d.ts +90 -0
- package/dist/src/agents/narrator.js +473 -0
- package/dist/src/agents/planner.d.ts +38 -0
- package/dist/src/agents/planner.js +341 -0
- package/dist/src/agents/predictor.d.ts +73 -0
- package/dist/src/agents/predictor.js +506 -0
- package/dist/src/agents/sensor.d.ts +88 -0
- package/dist/src/agents/sensor.js +377 -0
- package/dist/src/agents/test-agents.d.ts +6 -0
- package/dist/src/agents/test-agents.js +73 -0
- package/dist/src/agents/types.d.ts +194 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/brain/index.d.ts +185 -0
- package/dist/src/brain/index.js +843 -0
- package/dist/src/brain/trace.d.ts +91 -0
- package/dist/src/brain/trace.js +327 -0
- package/dist/src/brain/types.d.ts +165 -0
- package/dist/src/brain/types.js +51 -0
- package/dist/src/cli/chat.d.ts +237 -0
- package/dist/src/cli/chat.js +1959 -0
- package/dist/src/cli/dispatcher.d.ts +182 -0
- package/dist/src/cli/dispatcher.js +718 -0
- package/dist/src/cli/human-loop.d.ts +170 -0
- package/dist/src/cli/human-loop.js +543 -0
- package/dist/src/cli/index.d.ts +12 -0
- package/dist/src/cli/index.js +28 -0
- package/dist/src/cli/interactive.d.ts +141 -0
- package/dist/src/cli/interactive.js +757 -0
- package/dist/src/cli/ui.d.ts +205 -0
- package/dist/src/cli/ui.js +632 -0
- package/dist/src/consciousness/attention-schema.d.ts +154 -0
- package/dist/src/consciousness/attention-schema.js +432 -0
- package/dist/src/consciousness/global-workspace.d.ts +149 -0
- package/dist/src/consciousness/global-workspace.js +422 -0
- package/dist/src/consciousness/index.d.ts +186 -0
- package/dist/src/consciousness/index.js +476 -0
- package/dist/src/consciousness/phi-calculator.d.ts +119 -0
- package/dist/src/consciousness/phi-calculator.js +445 -0
- package/dist/src/consciousness/phi-decisions.d.ts +169 -0
- package/dist/src/consciousness/phi-decisions.js +383 -0
- package/dist/src/consciousness/phi-monitor.d.ts +153 -0
- package/dist/src/consciousness/phi-monitor.js +465 -0
- package/dist/src/consciousness/types.d.ts +260 -0
- package/dist/src/consciousness/types.js +44 -0
- package/dist/src/daemon/dream-mode.d.ts +115 -0
- package/dist/src/daemon/dream-mode.js +470 -0
- package/dist/src/daemon/index.d.ts +162 -0
- package/dist/src/daemon/index.js +542 -0
- package/dist/src/daemon/maintenance.d.ts +139 -0
- package/dist/src/daemon/maintenance.js +549 -0
- package/dist/src/daemon/process.d.ts +82 -0
- package/dist/src/daemon/process.js +442 -0
- package/dist/src/daemon/scheduler.d.ts +90 -0
- package/dist/src/daemon/scheduler.js +494 -0
- package/dist/src/daemon/types.d.ts +213 -0
- package/dist/src/daemon/types.js +50 -0
- package/dist/src/epistemic/index.d.ts +74 -0
- package/dist/src/epistemic/index.js +225 -0
- package/dist/src/grounding/epistemic-stack.d.ts +100 -0
- package/dist/src/grounding/epistemic-stack.js +408 -0
- package/dist/src/grounding/feedback.d.ts +98 -0
- package/dist/src/grounding/feedback.js +276 -0
- package/dist/src/grounding/index.d.ts +123 -0
- package/dist/src/grounding/index.js +224 -0
- package/dist/src/grounding/verifier.d.ts +149 -0
- package/dist/src/grounding/verifier.js +484 -0
- package/dist/src/healing/detector.d.ts +110 -0
- package/dist/src/healing/detector.js +436 -0
- package/dist/src/healing/fixer.d.ts +138 -0
- package/dist/src/healing/fixer.js +572 -0
- package/dist/src/healing/index.d.ts +23 -0
- package/dist/src/healing/index.js +43 -0
- package/dist/src/hooks/index.d.ts +135 -0
- package/dist/src/hooks/index.js +317 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.js +1266 -0
- package/dist/src/kernel/index.d.ts +155 -0
- package/dist/src/kernel/index.js +795 -0
- package/dist/src/kernel/invariants.d.ts +153 -0
- package/dist/src/kernel/invariants.js +355 -0
- package/dist/src/kernel/test-kernel.d.ts +6 -0
- package/dist/src/kernel/test-kernel.js +108 -0
- package/dist/src/kernel/test-real-mcp.d.ts +10 -0
- package/dist/src/kernel/test-real-mcp.js +295 -0
- package/dist/src/llm/index.d.ts +146 -0
- package/dist/src/llm/index.js +428 -0
- package/dist/src/llm/router.d.ts +136 -0
- package/dist/src/llm/router.js +510 -0
- package/dist/src/mcp/index.d.ts +85 -0
- package/dist/src/mcp/index.js +657 -0
- package/dist/src/mcp/resilient.d.ts +139 -0
- package/dist/src/mcp/resilient.js +417 -0
- package/dist/src/memory/cache.d.ts +118 -0
- package/dist/src/memory/cache.js +356 -0
- package/dist/src/memory/cognitive-workspace.d.ts +231 -0
- package/dist/src/memory/cognitive-workspace.js +521 -0
- package/dist/src/memory/consolidation.d.ts +99 -0
- package/dist/src/memory/consolidation.js +443 -0
- package/dist/src/memory/episodic.d.ts +114 -0
- package/dist/src/memory/episodic.js +394 -0
- package/dist/src/memory/forgetting.d.ts +134 -0
- package/dist/src/memory/forgetting.js +324 -0
- package/dist/src/memory/index.d.ts +211 -0
- package/dist/src/memory/index.js +367 -0
- package/dist/src/memory/indexer.d.ts +123 -0
- package/dist/src/memory/indexer.js +479 -0
- package/dist/src/memory/procedural.d.ts +136 -0
- package/dist/src/memory/procedural.js +479 -0
- package/dist/src/memory/semantic.d.ts +132 -0
- package/dist/src/memory/semantic.js +497 -0
- package/dist/src/memory/types.d.ts +193 -0
- package/dist/src/memory/types.js +15 -0
- package/dist/src/orchestrator.d.ts +65 -0
- package/dist/src/orchestrator.js +317 -0
- package/dist/src/persistence/index.d.ts +257 -0
- package/dist/src/persistence/index.js +763 -0
- package/dist/src/pipeline/executor.d.ts +51 -0
- package/dist/src/pipeline/executor.js +695 -0
- package/dist/src/pipeline/index.d.ts +7 -0
- package/dist/src/pipeline/index.js +11 -0
- package/dist/src/self-production.d.ts +67 -0
- package/dist/src/self-production.js +205 -0
- package/dist/src/subagents/executor.d.ts +58 -0
- package/dist/src/subagents/executor.js +283 -0
- package/dist/src/subagents/index.d.ts +37 -0
- package/dist/src/subagents/index.js +53 -0
- package/dist/src/subagents/registry.d.ts +23 -0
- package/dist/src/subagents/registry.js +167 -0
- package/dist/src/subagents/types.d.ts +79 -0
- package/dist/src/subagents/types.js +14 -0
- package/dist/src/tools/bash.d.ts +139 -0
- package/dist/src/tools/bash.js +583 -0
- package/dist/src/tools/edit.d.ts +125 -0
- package/dist/src/tools/edit.js +424 -0
- package/dist/src/tools/git.d.ts +179 -0
- package/dist/src/tools/git.js +504 -0
- package/dist/src/tools/index.d.ts +21 -0
- package/dist/src/tools/index.js +163 -0
- package/dist/src/types.d.ts +145 -0
- package/dist/src/types.js +7 -0
- package/dist/src/world-model/decoder.d.ts +163 -0
- package/dist/src/world-model/decoder.js +517 -0
- package/dist/src/world-model/digital-twin.d.ts +219 -0
- package/dist/src/world-model/digital-twin.js +695 -0
- package/dist/src/world-model/encoder.d.ts +141 -0
- package/dist/src/world-model/encoder.js +564 -0
- package/dist/src/world-model/index.d.ts +221 -0
- package/dist/src/world-model/index.js +772 -0
- package/dist/src/world-model/predictor.d.ts +161 -0
- package/dist/src/world-model/predictor.js +681 -0
- package/dist/src/world-model/test-value-jepa.d.ts +8 -0
- package/dist/src/world-model/test-value-jepa.js +430 -0
- package/dist/src/world-model/types.d.ts +341 -0
- package/dist/src/world-model/types.js +69 -0
- package/dist/src/world-model/value-jepa.d.ts +247 -0
- package/dist/src/world-model/value-jepa.js +622 -0
- package/dist/test/brain.test.d.ts +11 -0
- package/dist/test/brain.test.js +358 -0
- package/dist/test/cli/dispatcher.test.d.ts +4 -0
- package/dist/test/cli/dispatcher.test.js +332 -0
- package/dist/test/cli/human-loop.test.d.ts +4 -0
- package/dist/test/cli/human-loop.test.js +270 -0
- package/dist/test/grounding/feedback.test.d.ts +4 -0
- package/dist/test/grounding/feedback.test.js +462 -0
- package/dist/test/grounding/verifier.test.d.ts +4 -0
- package/dist/test/grounding/verifier.test.js +442 -0
- package/dist/test/grounding.test.d.ts +6 -0
- package/dist/test/grounding.test.js +246 -0
- package/dist/test/healing/detector.test.d.ts +4 -0
- package/dist/test/healing/detector.test.js +266 -0
- package/dist/test/healing/fixer.test.d.ts +4 -0
- package/dist/test/healing/fixer.test.js +369 -0
- package/dist/test/integration.test.d.ts +5 -0
- package/dist/test/integration.test.js +290 -0
- package/dist/test/tools/bash.test.d.ts +4 -0
- package/dist/test/tools/bash.test.js +348 -0
- package/dist/test/tools/edit.test.d.ts +4 -0
- package/dist/test/tools/edit.test.js +350 -0
- package/dist/test/tools/git.test.d.ts +4 -0
- package/dist/test/tools/git.test.js +350 -0
- package/package.json +60 -0
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis 6.8 - Real MCP Client Module
|
|
4
|
+
*
|
|
5
|
+
* Connects to actual MCP servers using @modelcontextprotocol/sdk.
|
|
6
|
+
* Spawns servers on demand and manages connections.
|
|
7
|
+
*
|
|
8
|
+
* Environment Variables:
|
|
9
|
+
* - GENESIS_MCP_MODE: 'real' | 'simulated' | 'hybrid' (default: 'simulated')
|
|
10
|
+
* - GENESIS_MCP_TIMEOUT: Timeout in ms (default: 30000)
|
|
11
|
+
* - GENESIS_MCP_LOG: Enable MCP call logging (default: false)
|
|
12
|
+
*/
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
25
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.MCP_SERVER_REGISTRY = exports.mcpClient = void 0;
|
|
29
|
+
exports.getMCPClient = getMCPClient;
|
|
30
|
+
exports.resetMCPClient = resetMCPClient;
|
|
31
|
+
exports.isSimulatedMode = isSimulatedMode;
|
|
32
|
+
exports.isSimulatedResult = isSimulatedResult;
|
|
33
|
+
exports.logMCPMode = logMCPMode;
|
|
34
|
+
// Re-export Phase 8: Resilient MCP Wrapper
|
|
35
|
+
__exportStar(require("./resilient.js"), exports);
|
|
36
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
37
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
38
|
+
const crypto_1 = require("crypto");
|
|
39
|
+
/**
|
|
40
|
+
* Registry of MCP servers and how to spawn them.
|
|
41
|
+
* These are the 13 MCP servers Genesis uses.
|
|
42
|
+
*
|
|
43
|
+
* Package sources (verified on npm):
|
|
44
|
+
* - Official: @modelcontextprotocol/server-*
|
|
45
|
+
* - Third-party: arxiv-mcp-server, @brave/brave-search-mcp-server, etc.
|
|
46
|
+
*/
|
|
47
|
+
const MCP_SERVER_REGISTRY = {
|
|
48
|
+
// KNOWLEDGE
|
|
49
|
+
'arxiv': {
|
|
50
|
+
command: 'npx',
|
|
51
|
+
args: ['-y', '@iflow-mcp/arxiv-paper-mcp@latest'],
|
|
52
|
+
tools: ['search_arxiv', 'parse_paper_content', 'get_recent_ai_papers', 'get_arxiv_pdf_url'],
|
|
53
|
+
},
|
|
54
|
+
'semantic-scholar': {
|
|
55
|
+
command: 'npx',
|
|
56
|
+
args: ['-y', 'researchmcp', 'semantic'],
|
|
57
|
+
tools: ['search_semantic_scholar', 'get_semantic_scholar_paper', 'get_paper_citations', 'semantic_scholar_to_bibtex'],
|
|
58
|
+
},
|
|
59
|
+
'context7': {
|
|
60
|
+
command: 'npx',
|
|
61
|
+
args: ['-y', '@upstash/context7-mcp@latest'],
|
|
62
|
+
tools: ['resolve-library-id', 'query-docs'],
|
|
63
|
+
},
|
|
64
|
+
'wolfram': {
|
|
65
|
+
command: 'npx',
|
|
66
|
+
args: ['-y', 'wolfram-mcp'],
|
|
67
|
+
envVars: () => ({ WOLFRAM_APP_ID: process.env.WOLFRAM_APP_ID || '' }),
|
|
68
|
+
tools: ['wolfram_query'],
|
|
69
|
+
},
|
|
70
|
+
// RESEARCH
|
|
71
|
+
'gemini': {
|
|
72
|
+
command: 'npx',
|
|
73
|
+
args: ['-y', 'mcp-gemini-web'],
|
|
74
|
+
envVars: () => ({ GOOGLE_API_KEY: process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY || '' }),
|
|
75
|
+
tools: ['web_search', 'web_search_batch', 'health_check'],
|
|
76
|
+
},
|
|
77
|
+
'brave-search': {
|
|
78
|
+
command: 'npx',
|
|
79
|
+
args: () => ['-y', '@brave/brave-search-mcp-server', '--brave-api-key', process.env.BRAVE_API_KEY || ''],
|
|
80
|
+
tools: ['brave_web_search', 'brave_local_search', 'brave_news_search', 'brave_image_search', 'brave_video_search'],
|
|
81
|
+
},
|
|
82
|
+
'exa': {
|
|
83
|
+
command: 'npx',
|
|
84
|
+
args: ['-y', 'exa-mcp-server'],
|
|
85
|
+
envVars: () => ({ EXA_API_KEY: process.env.EXA_API_KEY || '' }),
|
|
86
|
+
tools: ['web_search_exa', 'get_code_context_exa'],
|
|
87
|
+
},
|
|
88
|
+
'firecrawl': {
|
|
89
|
+
command: 'npx',
|
|
90
|
+
args: ['-y', 'firecrawl-mcp'],
|
|
91
|
+
envVars: () => ({ FIRECRAWL_API_KEY: process.env.FIRECRAWL_API_KEY || '' }),
|
|
92
|
+
tools: ['firecrawl_scrape', 'firecrawl_search', 'firecrawl_map', 'firecrawl_crawl', 'firecrawl_extract'],
|
|
93
|
+
},
|
|
94
|
+
// CREATION
|
|
95
|
+
'openai': {
|
|
96
|
+
command: 'npx',
|
|
97
|
+
args: ['-y', '@mzxrai/mcp-openai'],
|
|
98
|
+
envVars: () => ({ OPENAI_API_KEY: process.env.OPENAI_API_KEY || '' }),
|
|
99
|
+
tools: ['openai_chat'],
|
|
100
|
+
},
|
|
101
|
+
'github': {
|
|
102
|
+
command: 'npx',
|
|
103
|
+
args: ['-y', '@modelcontextprotocol/server-github'],
|
|
104
|
+
// v7.3: Accept both variable names for compatibility
|
|
105
|
+
envVars: () => ({
|
|
106
|
+
GITHUB_PERSONAL_ACCESS_TOKEN: process.env.GITHUB_PERSONAL_ACCESS_TOKEN || process.env.GITHUB_TOKEN || ''
|
|
107
|
+
}),
|
|
108
|
+
tools: ['create_repository', 'search_repositories', 'create_issue', 'create_pull_request', 'get_file_contents'],
|
|
109
|
+
},
|
|
110
|
+
// VISUAL
|
|
111
|
+
'stability-ai': {
|
|
112
|
+
command: 'npx',
|
|
113
|
+
args: ['-y', 'mcp-server-stability-ai'],
|
|
114
|
+
envVars: () => ({ STABILITY_AI_API_KEY: process.env.STABILITY_AI_API_KEY || '' }),
|
|
115
|
+
tools: ['stability-ai-generate-image', 'stability-ai-generate-image-sd35', 'stability-ai-0-list-resources'],
|
|
116
|
+
},
|
|
117
|
+
// STORAGE
|
|
118
|
+
'memory': {
|
|
119
|
+
command: 'npx',
|
|
120
|
+
args: ['-y', '@modelcontextprotocol/server-memory'],
|
|
121
|
+
tools: ['create_entities', 'create_relations', 'search_nodes', 'read_graph', 'add_observations'],
|
|
122
|
+
},
|
|
123
|
+
'filesystem': {
|
|
124
|
+
command: 'npx',
|
|
125
|
+
args: () => ['-y', '@modelcontextprotocol/server-filesystem', process.env.HOME || '/tmp'],
|
|
126
|
+
tools: ['read_file', 'read_text_file', 'write_file', 'list_directory', 'search_files', 'create_directory'],
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
exports.MCP_SERVER_REGISTRY = MCP_SERVER_REGISTRY;
|
|
130
|
+
class MCPConnectionManager {
|
|
131
|
+
connections = new Map();
|
|
132
|
+
connecting = new Map();
|
|
133
|
+
timeout;
|
|
134
|
+
logCalls;
|
|
135
|
+
constructor(timeout = 30000, logCalls = false) {
|
|
136
|
+
this.timeout = timeout;
|
|
137
|
+
this.logCalls = logCalls;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get or create connection to MCP server
|
|
141
|
+
*/
|
|
142
|
+
async getConnection(server) {
|
|
143
|
+
// Return existing connection if available
|
|
144
|
+
const existing = this.connections.get(server);
|
|
145
|
+
if (existing?.connected) {
|
|
146
|
+
existing.lastUsed = new Date();
|
|
147
|
+
return existing;
|
|
148
|
+
}
|
|
149
|
+
// Check if already connecting
|
|
150
|
+
const pending = this.connecting.get(server);
|
|
151
|
+
if (pending) {
|
|
152
|
+
return pending;
|
|
153
|
+
}
|
|
154
|
+
// Create new connection
|
|
155
|
+
const connectPromise = this.createConnection(server);
|
|
156
|
+
this.connecting.set(server, connectPromise);
|
|
157
|
+
try {
|
|
158
|
+
const connection = await connectPromise;
|
|
159
|
+
this.connections.set(server, connection);
|
|
160
|
+
return connection;
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
this.connecting.delete(server);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Create new connection to MCP server
|
|
168
|
+
*/
|
|
169
|
+
async createConnection(server) {
|
|
170
|
+
const serverInfo = MCP_SERVER_REGISTRY[server];
|
|
171
|
+
if (!serverInfo) {
|
|
172
|
+
throw new Error(`Unknown MCP server: ${server}`);
|
|
173
|
+
}
|
|
174
|
+
// v7.3: Check required API keys before spawning
|
|
175
|
+
const missingKey = this.checkRequiredKeys(server);
|
|
176
|
+
if (missingKey) {
|
|
177
|
+
throw new Error(`MCP server '${server}' requires ${missingKey} to be set. Please add it to your .env file.`);
|
|
178
|
+
}
|
|
179
|
+
// Resolve args and envVars at connection time (supports functions for dynamic values)
|
|
180
|
+
const args = typeof serverInfo.args === 'function' ? serverInfo.args() : serverInfo.args;
|
|
181
|
+
const envVars = typeof serverInfo.envVars === 'function' ? serverInfo.envVars() : serverInfo.envVars;
|
|
182
|
+
if (this.logCalls) {
|
|
183
|
+
console.log(`[MCP] Spawning ${server}: ${serverInfo.command} ${args.join(' ')}`);
|
|
184
|
+
}
|
|
185
|
+
const client = new index_js_1.Client({
|
|
186
|
+
name: `genesis-${server}`,
|
|
187
|
+
version: '6.0.0',
|
|
188
|
+
});
|
|
189
|
+
// Build environment, filtering out undefined values
|
|
190
|
+
const env = {};
|
|
191
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
192
|
+
if (value !== undefined) {
|
|
193
|
+
env[key] = value;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (envVars) {
|
|
197
|
+
Object.assign(env, envVars);
|
|
198
|
+
}
|
|
199
|
+
const transport = new stdio_js_1.StdioClientTransport({
|
|
200
|
+
command: serverInfo.command,
|
|
201
|
+
args,
|
|
202
|
+
env,
|
|
203
|
+
});
|
|
204
|
+
await client.connect(transport);
|
|
205
|
+
if (this.logCalls) {
|
|
206
|
+
console.log(`[MCP] Connected to ${server}`);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
client,
|
|
210
|
+
transport,
|
|
211
|
+
connected: true,
|
|
212
|
+
lastUsed: new Date(),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Call a tool on an MCP server
|
|
217
|
+
*/
|
|
218
|
+
async callTool(server, tool, args) {
|
|
219
|
+
const connection = await this.getConnection(server);
|
|
220
|
+
if (this.logCalls) {
|
|
221
|
+
console.log(`[MCP] ${server}.${tool}(${JSON.stringify(args).slice(0, 100)}...)`);
|
|
222
|
+
}
|
|
223
|
+
const result = await connection.client.callTool({
|
|
224
|
+
name: tool,
|
|
225
|
+
arguments: args,
|
|
226
|
+
});
|
|
227
|
+
// Parse result content
|
|
228
|
+
const content = result.content;
|
|
229
|
+
if (content && content.length > 0) {
|
|
230
|
+
const first = content[0];
|
|
231
|
+
if (first.type === 'text' && typeof first.text === 'string') {
|
|
232
|
+
try {
|
|
233
|
+
return JSON.parse(first.text);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return first.text;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* List available tools on an MCP server (names only)
|
|
244
|
+
*/
|
|
245
|
+
async listTools(server) {
|
|
246
|
+
const connection = await this.getConnection(server);
|
|
247
|
+
const result = await connection.client.listTools();
|
|
248
|
+
return result.tools.map((t) => t.name);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* List available tools with full schema (for dynamic prompt building)
|
|
252
|
+
*/
|
|
253
|
+
async listToolsWithSchema(server) {
|
|
254
|
+
const connection = await this.getConnection(server);
|
|
255
|
+
const result = await connection.client.listTools();
|
|
256
|
+
return result.tools.map((t) => ({
|
|
257
|
+
name: t.name,
|
|
258
|
+
description: t.description,
|
|
259
|
+
inputSchema: t.inputSchema,
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Check if a server is available (can connect)
|
|
264
|
+
*/
|
|
265
|
+
async isAvailable(server) {
|
|
266
|
+
try {
|
|
267
|
+
await this.getConnection(server);
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Close connection to a server
|
|
276
|
+
*/
|
|
277
|
+
async closeConnection(server) {
|
|
278
|
+
const connection = this.connections.get(server);
|
|
279
|
+
if (connection) {
|
|
280
|
+
try {
|
|
281
|
+
await connection.client.close();
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// Ignore close errors
|
|
285
|
+
}
|
|
286
|
+
connection.connected = false;
|
|
287
|
+
this.connections.delete(server);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Close all connections
|
|
292
|
+
*/
|
|
293
|
+
async closeAll() {
|
|
294
|
+
const servers = Array.from(this.connections.keys());
|
|
295
|
+
await Promise.all(servers.map((s) => this.closeConnection(s)));
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* v7.3: Check if required API keys are set for a server
|
|
299
|
+
* Returns the name of the missing key, or null if all keys are present
|
|
300
|
+
*/
|
|
301
|
+
checkRequiredKeys(server) {
|
|
302
|
+
// Map of servers to their required environment variables
|
|
303
|
+
const requiredKeys = {
|
|
304
|
+
'wolfram': ['WOLFRAM_APP_ID'],
|
|
305
|
+
'brave-search': ['BRAVE_API_KEY'],
|
|
306
|
+
'exa': ['EXA_API_KEY'],
|
|
307
|
+
'firecrawl': ['FIRECRAWL_API_KEY'],
|
|
308
|
+
'openai': ['OPENAI_API_KEY'],
|
|
309
|
+
'github': ['GITHUB_PERSONAL_ACCESS_TOKEN', 'GITHUB_TOKEN'], // Either one
|
|
310
|
+
'stability-ai': ['STABILITY_AI_API_KEY'],
|
|
311
|
+
'gemini': ['GOOGLE_API_KEY', 'GEMINI_API_KEY'], // Either one
|
|
312
|
+
// These don't need API keys:
|
|
313
|
+
// 'arxiv', 'semantic-scholar', 'context7', 'memory', 'filesystem'
|
|
314
|
+
};
|
|
315
|
+
const keys = requiredKeys[server];
|
|
316
|
+
if (!keys)
|
|
317
|
+
return null; // No required keys
|
|
318
|
+
// For servers that accept either of multiple keys (like github, gemini)
|
|
319
|
+
// Check if at least one is set
|
|
320
|
+
const hasAtLeastOne = keys.some(key => !!process.env[key]);
|
|
321
|
+
if (!hasAtLeastOne) {
|
|
322
|
+
return keys.join(' or ');
|
|
323
|
+
}
|
|
324
|
+
return null; // All required keys present
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
// ============================================================================
|
|
328
|
+
// Real MCP Client
|
|
329
|
+
// ============================================================================
|
|
330
|
+
class RealMCPClient {
|
|
331
|
+
manager;
|
|
332
|
+
mode = 'real';
|
|
333
|
+
config;
|
|
334
|
+
constructor(config = {}) {
|
|
335
|
+
this.config = {
|
|
336
|
+
mode: 'real',
|
|
337
|
+
timeout: 30000,
|
|
338
|
+
logCalls: false,
|
|
339
|
+
...config,
|
|
340
|
+
};
|
|
341
|
+
this.mode = this.config.mode;
|
|
342
|
+
this.manager = new MCPConnectionManager(this.config.timeout, this.config.logCalls);
|
|
343
|
+
}
|
|
344
|
+
async call(server, tool, params, options = {}) {
|
|
345
|
+
const startTime = Date.now();
|
|
346
|
+
if (this.config.onCall) {
|
|
347
|
+
this.config.onCall(server, tool, params);
|
|
348
|
+
}
|
|
349
|
+
try {
|
|
350
|
+
const data = await this.manager.callTool(server, tool, params);
|
|
351
|
+
const result = {
|
|
352
|
+
success: true,
|
|
353
|
+
data,
|
|
354
|
+
server,
|
|
355
|
+
tool,
|
|
356
|
+
mode: 'real',
|
|
357
|
+
latency: Date.now() - startTime,
|
|
358
|
+
timestamp: new Date(),
|
|
359
|
+
};
|
|
360
|
+
if (this.config.onResult) {
|
|
361
|
+
this.config.onResult(result);
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
const result = {
|
|
367
|
+
success: false,
|
|
368
|
+
error: error instanceof Error ? error.message : String(error),
|
|
369
|
+
server,
|
|
370
|
+
tool,
|
|
371
|
+
mode: 'real',
|
|
372
|
+
latency: Date.now() - startTime,
|
|
373
|
+
timestamp: new Date(),
|
|
374
|
+
};
|
|
375
|
+
if (this.config.onResult) {
|
|
376
|
+
this.config.onResult(result);
|
|
377
|
+
}
|
|
378
|
+
return result;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
async listTools(server) {
|
|
382
|
+
return this.manager.listTools(server);
|
|
383
|
+
}
|
|
384
|
+
async listToolsWithSchema(server) {
|
|
385
|
+
return this.manager.listToolsWithSchema(server);
|
|
386
|
+
}
|
|
387
|
+
async discoverAllTools() {
|
|
388
|
+
const result = {};
|
|
389
|
+
const servers = Object.keys(MCP_SERVER_REGISTRY);
|
|
390
|
+
// Discover tools from all servers in parallel
|
|
391
|
+
await Promise.allSettled(servers.map(async (server) => {
|
|
392
|
+
try {
|
|
393
|
+
result[server] = await this.listToolsWithSchema(server);
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
// Server not available, use registry fallback
|
|
397
|
+
result[server] = MCP_SERVER_REGISTRY[server].tools.map(name => ({ name }));
|
|
398
|
+
}
|
|
399
|
+
}));
|
|
400
|
+
return result;
|
|
401
|
+
}
|
|
402
|
+
async isAvailable(server) {
|
|
403
|
+
return this.manager.isAvailable(server);
|
|
404
|
+
}
|
|
405
|
+
getMode() {
|
|
406
|
+
return this.mode;
|
|
407
|
+
}
|
|
408
|
+
setMode(mode) {
|
|
409
|
+
this.mode = mode;
|
|
410
|
+
}
|
|
411
|
+
async close() {
|
|
412
|
+
await this.manager.closeAll();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// ============================================================================
|
|
416
|
+
// Simulated MCP Client (for testing without real servers)
|
|
417
|
+
// ============================================================================
|
|
418
|
+
class SimulatedMCPClient {
|
|
419
|
+
mode = 'simulated';
|
|
420
|
+
config;
|
|
421
|
+
constructor(config = {}) {
|
|
422
|
+
this.config = {
|
|
423
|
+
mode: 'simulated',
|
|
424
|
+
timeout: 30000,
|
|
425
|
+
logCalls: false,
|
|
426
|
+
...config,
|
|
427
|
+
};
|
|
428
|
+
this.mode = this.config.mode;
|
|
429
|
+
}
|
|
430
|
+
async call(server, tool, params, options = {}) {
|
|
431
|
+
const startTime = Date.now();
|
|
432
|
+
if (this.config.onCall) {
|
|
433
|
+
this.config.onCall(server, tool, params);
|
|
434
|
+
}
|
|
435
|
+
if (this.config.logCalls) {
|
|
436
|
+
console.log(`[MCP:SIM] ${server}.${tool}(${JSON.stringify(params).slice(0, 100)}...)`);
|
|
437
|
+
}
|
|
438
|
+
// Simulate latency
|
|
439
|
+
await new Promise((r) => setTimeout(r, 50 + Math.random() * 150));
|
|
440
|
+
const data = this.generateSimulatedResponse(server, tool, params);
|
|
441
|
+
const result = {
|
|
442
|
+
success: true,
|
|
443
|
+
data,
|
|
444
|
+
server,
|
|
445
|
+
tool,
|
|
446
|
+
mode: 'simulated',
|
|
447
|
+
latency: Date.now() - startTime,
|
|
448
|
+
timestamp: new Date(),
|
|
449
|
+
};
|
|
450
|
+
if (this.config.onResult) {
|
|
451
|
+
this.config.onResult(result);
|
|
452
|
+
}
|
|
453
|
+
return result;
|
|
454
|
+
}
|
|
455
|
+
async listTools(server) {
|
|
456
|
+
return MCP_SERVER_REGISTRY[server]?.tools || [];
|
|
457
|
+
}
|
|
458
|
+
async listToolsWithSchema(server) {
|
|
459
|
+
// In simulated mode, return basic tool info from registry
|
|
460
|
+
const tools = MCP_SERVER_REGISTRY[server]?.tools || [];
|
|
461
|
+
return tools.map(name => ({
|
|
462
|
+
name,
|
|
463
|
+
description: `[Simulated] ${name} tool`,
|
|
464
|
+
}));
|
|
465
|
+
}
|
|
466
|
+
async discoverAllTools() {
|
|
467
|
+
const result = {};
|
|
468
|
+
const servers = Object.keys(MCP_SERVER_REGISTRY);
|
|
469
|
+
for (const server of servers) {
|
|
470
|
+
result[server] = await this.listToolsWithSchema(server);
|
|
471
|
+
}
|
|
472
|
+
return result;
|
|
473
|
+
}
|
|
474
|
+
async isAvailable(server) {
|
|
475
|
+
return true; // Always available in simulated mode
|
|
476
|
+
}
|
|
477
|
+
getMode() {
|
|
478
|
+
return this.mode;
|
|
479
|
+
}
|
|
480
|
+
setMode(mode) {
|
|
481
|
+
this.mode = mode;
|
|
482
|
+
}
|
|
483
|
+
async close() {
|
|
484
|
+
// No-op for simulated
|
|
485
|
+
}
|
|
486
|
+
generateSimulatedResponse(server, tool, params) {
|
|
487
|
+
const query = params.query || params.q || params.input || 'query';
|
|
488
|
+
switch (server) {
|
|
489
|
+
case 'arxiv':
|
|
490
|
+
return {
|
|
491
|
+
papers: [{
|
|
492
|
+
id: 'arxiv:' + (0, crypto_1.randomUUID)().slice(0, 8),
|
|
493
|
+
title: `[SIM] Research on ${query}`,
|
|
494
|
+
authors: ['Author A', 'Author B'],
|
|
495
|
+
abstract: `Simulated paper about ${query}.`,
|
|
496
|
+
url: `https://arxiv.org/abs/${(0, crypto_1.randomUUID)().slice(0, 8)}`,
|
|
497
|
+
}],
|
|
498
|
+
_simulated: true,
|
|
499
|
+
};
|
|
500
|
+
case 'semantic-scholar':
|
|
501
|
+
return {
|
|
502
|
+
papers: [{
|
|
503
|
+
paperId: (0, crypto_1.randomUUID)().slice(0, 8),
|
|
504
|
+
title: `[SIM] ${query} Study`,
|
|
505
|
+
citationCount: Math.floor(Math.random() * 100),
|
|
506
|
+
}],
|
|
507
|
+
_simulated: true,
|
|
508
|
+
};
|
|
509
|
+
case 'brave-search':
|
|
510
|
+
case 'gemini':
|
|
511
|
+
case 'exa':
|
|
512
|
+
return {
|
|
513
|
+
results: [{
|
|
514
|
+
title: `[SIM] ${query} Result`,
|
|
515
|
+
url: 'https://example.com/sim',
|
|
516
|
+
description: `Simulated result for ${query}`,
|
|
517
|
+
}],
|
|
518
|
+
_simulated: true,
|
|
519
|
+
};
|
|
520
|
+
case 'firecrawl':
|
|
521
|
+
return {
|
|
522
|
+
content: `[SIM] Scraped content for ${params.url || query}`,
|
|
523
|
+
_simulated: true,
|
|
524
|
+
};
|
|
525
|
+
case 'memory':
|
|
526
|
+
return { entities: [], relations: [], _simulated: true };
|
|
527
|
+
case 'filesystem':
|
|
528
|
+
return { content: `[SIM] File content`, _simulated: true };
|
|
529
|
+
default:
|
|
530
|
+
return { success: true, _simulated: true };
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// ============================================================================
|
|
535
|
+
// Hybrid MCP Client
|
|
536
|
+
// ============================================================================
|
|
537
|
+
class HybridMCPClient {
|
|
538
|
+
realClient;
|
|
539
|
+
simClient;
|
|
540
|
+
mode = 'hybrid';
|
|
541
|
+
config;
|
|
542
|
+
constructor(config = {}) {
|
|
543
|
+
this.config = {
|
|
544
|
+
mode: 'hybrid',
|
|
545
|
+
timeout: 30000,
|
|
546
|
+
logCalls: false,
|
|
547
|
+
...config,
|
|
548
|
+
};
|
|
549
|
+
this.realClient = new RealMCPClient(config);
|
|
550
|
+
this.simClient = new SimulatedMCPClient(config);
|
|
551
|
+
}
|
|
552
|
+
async call(server, tool, params, options = {}) {
|
|
553
|
+
// Try real first
|
|
554
|
+
const result = await this.realClient.call(server, tool, params, options);
|
|
555
|
+
// Fallback to simulated if real fails
|
|
556
|
+
if (!result.success && (options.fallbackToSimulated ?? true)) {
|
|
557
|
+
if (this.config.logCalls) {
|
|
558
|
+
console.log(`[MCP] Real call failed, falling back to simulated: ${result.error}`);
|
|
559
|
+
}
|
|
560
|
+
return this.simClient.call(server, tool, params, options);
|
|
561
|
+
}
|
|
562
|
+
return result;
|
|
563
|
+
}
|
|
564
|
+
async listTools(server) {
|
|
565
|
+
try {
|
|
566
|
+
return await this.realClient.listTools(server);
|
|
567
|
+
}
|
|
568
|
+
catch {
|
|
569
|
+
return this.simClient.listTools(server);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
async listToolsWithSchema(server) {
|
|
573
|
+
try {
|
|
574
|
+
return await this.realClient.listToolsWithSchema(server);
|
|
575
|
+
}
|
|
576
|
+
catch {
|
|
577
|
+
return this.simClient.listToolsWithSchema(server);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
async discoverAllTools() {
|
|
581
|
+
try {
|
|
582
|
+
return await this.realClient.discoverAllTools();
|
|
583
|
+
}
|
|
584
|
+
catch {
|
|
585
|
+
return this.simClient.discoverAllTools();
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
async isAvailable(server) {
|
|
589
|
+
return (await this.realClient.isAvailable(server)) ||
|
|
590
|
+
(await this.simClient.isAvailable(server));
|
|
591
|
+
}
|
|
592
|
+
getMode() {
|
|
593
|
+
return this.mode;
|
|
594
|
+
}
|
|
595
|
+
setMode(mode) {
|
|
596
|
+
this.mode = mode;
|
|
597
|
+
}
|
|
598
|
+
async close() {
|
|
599
|
+
await this.realClient.close();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
// ============================================================================
|
|
603
|
+
// Factory & Singleton
|
|
604
|
+
// ============================================================================
|
|
605
|
+
function createMCPClient(config = {}) {
|
|
606
|
+
// v7.0: Default changed from 'simulated' to 'real'
|
|
607
|
+
const mode = process.env.GENESIS_MCP_MODE || config.mode || 'real';
|
|
608
|
+
const timeout = parseInt(process.env.GENESIS_MCP_TIMEOUT || '') || config.timeout || 30000;
|
|
609
|
+
const logCalls = process.env.GENESIS_MCP_LOG === 'true' || config.logCalls || false;
|
|
610
|
+
const fullConfig = {
|
|
611
|
+
...config,
|
|
612
|
+
mode,
|
|
613
|
+
timeout,
|
|
614
|
+
logCalls,
|
|
615
|
+
};
|
|
616
|
+
// Log mode for transparency
|
|
617
|
+
if (logCalls) {
|
|
618
|
+
console.log(`[MCP] Mode: ${mode} (timeout: ${timeout}ms)`);
|
|
619
|
+
}
|
|
620
|
+
switch (mode) {
|
|
621
|
+
case 'real':
|
|
622
|
+
return new RealMCPClient(fullConfig);
|
|
623
|
+
case 'hybrid':
|
|
624
|
+
return new HybridMCPClient(fullConfig);
|
|
625
|
+
case 'simulated':
|
|
626
|
+
default:
|
|
627
|
+
return new SimulatedMCPClient(fullConfig);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
let mcpClientInstance = null;
|
|
631
|
+
function getMCPClient(config) {
|
|
632
|
+
if (!mcpClientInstance) {
|
|
633
|
+
mcpClientInstance = createMCPClient(config);
|
|
634
|
+
}
|
|
635
|
+
return mcpClientInstance;
|
|
636
|
+
}
|
|
637
|
+
function resetMCPClient() {
|
|
638
|
+
if (mcpClientInstance) {
|
|
639
|
+
mcpClientInstance.close().catch(() => { });
|
|
640
|
+
}
|
|
641
|
+
mcpClientInstance = null;
|
|
642
|
+
}
|
|
643
|
+
exports.mcpClient = getMCPClient();
|
|
644
|
+
// ============================================================================
|
|
645
|
+
// Utilities
|
|
646
|
+
// ============================================================================
|
|
647
|
+
function isSimulatedMode() {
|
|
648
|
+
return exports.mcpClient.getMode() === 'simulated';
|
|
649
|
+
}
|
|
650
|
+
function isSimulatedResult(result) {
|
|
651
|
+
return result.mode === 'simulated' || result.data?._simulated === true;
|
|
652
|
+
}
|
|
653
|
+
function logMCPMode() {
|
|
654
|
+
const mode = exports.mcpClient.getMode();
|
|
655
|
+
const emoji = mode === 'real' ? '🔌' : mode === 'hybrid' ? '🔀' : 'ðŸŽ';
|
|
656
|
+
console.log(`[Genesis] MCP Mode: ${emoji} ${mode.toUpperCase()}`);
|
|
657
|
+
}
|