nucleus-mcp 1.0.7 → 1.2.0
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 +2 -4
- package/.github/workflows/ci.yml +0 -72
- package/.smithery/shttp/module.js +0 -3
- package/.smithery/shttp/module.js.map +0 -7
- package/.smithery/stdio/index.cjs +0 -74
- package/.smithery/stdio/index.cjs.map +0 -7
- package/CHANGELOG.md +0 -65
- package/CODE_OF_CONDUCT.md +0 -34
- package/COMPARISON.md +0 -20
- package/CONTRIBUTING.md +0 -137
- package/DEVELOPMENT.md +0 -109
- package/LICENSE +0 -21
- package/README.md +0 -319
- package/ROADMAP.md +0 -24
- package/SECURITY.md +0 -88
- package/docs/COMMUNITY_FAQ.md +0 -48
- package/docs/COMPETITIVE_ANALYSIS.md +0 -90
- package/docs/DEMO_SCRIPT.md +0 -86
- package/docs/ENTERPRISE.md +0 -169
- package/docs/FAQ.md +0 -228
- package/docs/QUICK_START.md +0 -155
- package/docs/README.md +0 -67
- package/docs/RECURSIVE_SNAP_DEMO.gif +0 -0
- package/docs/social-preview-hq.png +0 -0
- package/docs/social-preview.png +0 -0
- package/examples/basic_usage.py +0 -84
- package/package.json.real +0 -24
- package/pyproject.toml +0 -50
- package/registry-server.json +0 -20
- package/scripts/demo_governance.py +0 -109
- package/scripts/sse_bridge.py +0 -87
- package/scripts/verify_windows_paths.py +0 -48
- package/server.json +0 -20
- package/src/mcp_server_nucleus/__init__.py +0 -8583
- package/src/mcp_server_nucleus/__main__.py +0 -9
- package/src/mcp_server_nucleus/cli.py +0 -1225
- package/src/mcp_server_nucleus/commitment_core.py +0 -146
- package/src/mcp_server_nucleus/commitment_ledger.py +0 -841
- package/src/mcp_server_nucleus/core/__init__.py +0 -6
- package/src/mcp_server_nucleus/core/orchestrator.py +0 -9
- package/src/mcp_server_nucleus/core/tool_registration_impl.py +0 -99
- package/src/mcp_server_nucleus/daemon/safety/lock.py +0 -121
- package/src/mcp_server_nucleus/deployment/render_integration.py +0 -4
- package/src/mcp_server_nucleus/hypervisor/__init__.py +0 -0
- package/src/mcp_server_nucleus/hypervisor/injector.py +0 -83
- package/src/mcp_server_nucleus/hypervisor/locker.py +0 -130
- package/src/mcp_server_nucleus/hypervisor/watchdog.py +0 -71
- package/src/mcp_server_nucleus/runtime/__init__.py +0 -58
- package/src/mcp_server_nucleus/runtime/agent.py +0 -517
- package/src/mcp_server_nucleus/runtime/agent_pool.py +0 -797
- package/src/mcp_server_nucleus/runtime/agents/base.py +0 -34
- package/src/mcp_server_nucleus/runtime/agents/oracle/manifest.json +0 -28
- package/src/mcp_server_nucleus/runtime/auth.py +0 -98
- package/src/mcp_server_nucleus/runtime/autopilot.py +0 -1057
- package/src/mcp_server_nucleus/runtime/broker.py +0 -126
- package/src/mcp_server_nucleus/runtime/budget.py +0 -153
- package/src/mcp_server_nucleus/runtime/capabilities/base.py +0 -20
- package/src/mcp_server_nucleus/runtime/capabilities/brain_ops.py +0 -253
- package/src/mcp_server_nucleus/runtime/capabilities/code_ops.py +0 -192
- package/src/mcp_server_nucleus/runtime/capabilities/depth_tracker.py +0 -81
- package/src/mcp_server_nucleus/runtime/capabilities/feature_map.py +0 -274
- package/src/mcp_server_nucleus/runtime/capabilities/marketing_engine.py +0 -205
- package/src/mcp_server_nucleus/runtime/capabilities/memory_ops.py +0 -79
- package/src/mcp_server_nucleus/runtime/capabilities/proof_system.py +0 -127
- package/src/mcp_server_nucleus/runtime/capabilities/render_ops.py +0 -80
- package/src/mcp_server_nucleus/runtime/capabilities/render_poller_cap.py +0 -266
- package/src/mcp_server_nucleus/runtime/capabilities/self_healing.py +0 -110
- package/src/mcp_server_nucleus/runtime/capabilities/strategy.py +0 -138
- package/src/mcp_server_nucleus/runtime/capabilities/synthesizer.py +0 -134
- package/src/mcp_server_nucleus/runtime/capabilities/web_ops.py +0 -94
- package/src/mcp_server_nucleus/runtime/common.py +0 -134
- package/src/mcp_server_nucleus/runtime/context_manager.py +0 -342
- package/src/mcp_server_nucleus/runtime/context_rules.json +0 -86
- package/src/mcp_server_nucleus/runtime/crdt_task_store.py +0 -349
- package/src/mcp_server_nucleus/runtime/critic.py +0 -150
- package/src/mcp_server_nucleus/runtime/daemon.py +0 -142
- package/src/mcp_server_nucleus/runtime/dashboard.py +0 -1087
- package/src/mcp_server_nucleus/runtime/depth_ops.py +0 -339
- package/src/mcp_server_nucleus/runtime/event_ops.py +0 -103
- package/src/mcp_server_nucleus/runtime/event_stream.py +0 -213
- package/src/mcp_server_nucleus/runtime/export.py +0 -64
- package/src/mcp_server_nucleus/runtime/factory.py +0 -594
- package/src/mcp_server_nucleus/runtime/federation.py +0 -1040
- package/src/mcp_server_nucleus/runtime/fetcher.py +0 -92
- package/src/mcp_server_nucleus/runtime/file_monitor.py +0 -208
- package/src/mcp_server_nucleus/runtime/firestore_bridge.py +0 -91
- package/src/mcp_server_nucleus/runtime/gcloud_ops.py +0 -186
- package/src/mcp_server_nucleus/runtime/hooks.py +0 -246
- package/src/mcp_server_nucleus/runtime/identity/gatekeeper.py +0 -106
- package/src/mcp_server_nucleus/runtime/identity/keygen.py +0 -147
- package/src/mcp_server_nucleus/runtime/identity/manifest.py +0 -62
- package/src/mcp_server_nucleus/runtime/identity/trust.py +0 -27
- package/src/mcp_server_nucleus/runtime/inspector.py +0 -74
- package/src/mcp_server_nucleus/runtime/installer.py +0 -81
- package/src/mcp_server_nucleus/runtime/ipc_auth.py +0 -377
- package/src/mcp_server_nucleus/runtime/lifecycle.py +0 -129
- package/src/mcp_server_nucleus/runtime/llm_client.py +0 -408
- package/src/mcp_server_nucleus/runtime/llm_tiers.json +0 -88
- package/src/mcp_server_nucleus/runtime/locking.py +0 -228
- package/src/mcp_server_nucleus/runtime/loops/fixer.py +0 -110
- package/src/mcp_server_nucleus/runtime/memory.py +0 -158
- package/src/mcp_server_nucleus/runtime/mounter.py +0 -210
- package/src/mcp_server_nucleus/runtime/mounter_ops.py +0 -250
- package/src/mcp_server_nucleus/runtime/nuke_protocol.py +0 -147
- package/src/mcp_server_nucleus/runtime/orchestrator.py +0 -370
- package/src/mcp_server_nucleus/runtime/orchestrator_unified.py +0 -263
- package/src/mcp_server_nucleus/runtime/orchestrator_v3.py +0 -617
- package/src/mcp_server_nucleus/runtime/plugin_loader.py +0 -84
- package/src/mcp_server_nucleus/runtime/policy.py +0 -117
- package/src/mcp_server_nucleus/runtime/profiling.py +0 -219
- package/src/mcp_server_nucleus/runtime/prometheus.py +0 -286
- package/src/mcp_server_nucleus/runtime/proposals.py +0 -101
- package/src/mcp_server_nucleus/runtime/publisher.py +0 -109
- package/src/mcp_server_nucleus/runtime/pulse.py +0 -516
- package/src/mcp_server_nucleus/runtime/registry.py +0 -82
- package/src/mcp_server_nucleus/runtime/render_ops.py +0 -83
- package/src/mcp_server_nucleus/runtime/schema_gen.py +0 -140
- package/src/mcp_server_nucleus/runtime/session_ops.py +0 -224
- package/src/mcp_server_nucleus/runtime/stdio_server.py +0 -633
- package/src/mcp_server_nucleus/runtime/storage.py +0 -83
- package/src/mcp_server_nucleus/runtime/strategy.py +0 -91
- package/src/mcp_server_nucleus/runtime/swarm.py +0 -170
- package/src/mcp_server_nucleus/runtime/sync_ops.py +0 -878
- package/src/mcp_server_nucleus/runtime/task_ingestion.py +0 -1020
- package/src/mcp_server_nucleus/runtime/task_ops.py +0 -449
- package/src/mcp_server_nucleus/runtime/task_scheduler.py +0 -488
- package/src/mcp_server_nucleus/runtime/team.py +0 -59
- package/src/mcp_server_nucleus/runtime/triggers.py +0 -237
- package/src/mcp_server_nucleus/runtime/vector_store.py +0 -125
- package/src/mcp_server_nucleus/runtime/watcher.py +0 -112
- package/src/mcp_server_nucleus/tool_tiers.py +0 -243
- package/tests/__init__.py +0 -1
- package/tests/conftest.py +0 -42
- package/tests/test_core.py +0 -235
- package/tests/test_search.py +0 -69
|
@@ -1,633 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import sys
|
|
3
|
-
import json
|
|
4
|
-
import logging
|
|
5
|
-
import traceback
|
|
6
|
-
import time
|
|
7
|
-
import os
|
|
8
|
-
import re
|
|
9
|
-
from typing import Any, Dict, Optional
|
|
10
|
-
from ..hypervisor.locker import Locker
|
|
11
|
-
from ..hypervisor.watchdog import Watchdog
|
|
12
|
-
from ..hypervisor.injector import Injector
|
|
13
|
-
from .task_ops import (
|
|
14
|
-
_list_tasks, _add_task, _update_task,
|
|
15
|
-
_claim_task, _get_next_task
|
|
16
|
-
)
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
from datetime import datetime
|
|
19
|
-
import asyncio
|
|
20
|
-
from .mounter_ops import Mounter
|
|
21
|
-
|
|
22
|
-
# Configure logging to stderr to not corrupt stdout (which is for JSON-RPC)
|
|
23
|
-
logging.basicConfig(stream=sys.stderr, level=logging.INFO, format='[Nucleus] %(message)s')
|
|
24
|
-
logger = logging.getLogger("nucleus_server")
|
|
25
|
-
|
|
26
|
-
START_TIME = time.time()
|
|
27
|
-
|
|
28
|
-
def make_response(success: bool, data: Any = None, error: str = None) -> str:
|
|
29
|
-
"""Helper to create a formatted JSON response string."""
|
|
30
|
-
response = {"success": success}
|
|
31
|
-
if data is not None:
|
|
32
|
-
response["data"] = data
|
|
33
|
-
if error is not None:
|
|
34
|
-
response["error"] = error
|
|
35
|
-
return json.dumps(response, indent=2)
|
|
36
|
-
|
|
37
|
-
class StdioServer:
|
|
38
|
-
def __init__(self):
|
|
39
|
-
# Resolve paths first
|
|
40
|
-
self.brain_path = Path(os.environ.get("NUCLEAR_BRAIN_PATH", ".")).resolve()
|
|
41
|
-
workspace_root = self.brain_path.parent
|
|
42
|
-
|
|
43
|
-
self.locker = Locker()
|
|
44
|
-
self.injector = Injector(str(workspace_root))
|
|
45
|
-
self.watchdog = Watchdog(str(workspace_root))
|
|
46
|
-
|
|
47
|
-
try:
|
|
48
|
-
self.watchdog.start()
|
|
49
|
-
except Exception as e:
|
|
50
|
-
logger.error(f"Failed to start watchdog: {e}")
|
|
51
|
-
|
|
52
|
-
self.mounter = Mounter(self.brain_path)
|
|
53
|
-
|
|
54
|
-
async def run(self):
|
|
55
|
-
# Restore mounts from persistence
|
|
56
|
-
await self.mounter.restore_mounts()
|
|
57
|
-
|
|
58
|
-
loop = asyncio.get_running_loop()
|
|
59
|
-
while True:
|
|
60
|
-
try:
|
|
61
|
-
line = await loop.run_in_executor(None, sys.stdin.readline)
|
|
62
|
-
if not line:
|
|
63
|
-
break
|
|
64
|
-
|
|
65
|
-
request = json.loads(line)
|
|
66
|
-
|
|
67
|
-
response = await self.handle_request(request)
|
|
68
|
-
if response:
|
|
69
|
-
out = json.dumps(response)
|
|
70
|
-
print(out, flush=True)
|
|
71
|
-
except json.JSONDecodeError:
|
|
72
|
-
logger.error("Failed to decode JSON")
|
|
73
|
-
except Exception as e:
|
|
74
|
-
logger.error(f"Server loop error: {e}")
|
|
75
|
-
traceback.print_exc(file=sys.stderr)
|
|
76
|
-
|
|
77
|
-
async def handle_request(self, request: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
78
|
-
method = request.get("method")
|
|
79
|
-
msg_id = request.get("id")
|
|
80
|
-
|
|
81
|
-
if method == "initialize":
|
|
82
|
-
return {
|
|
83
|
-
"jsonrpc": "2.0",
|
|
84
|
-
"id": msg_id,
|
|
85
|
-
"result": {
|
|
86
|
-
"protocolVersion": "2024-11-05", # Updated protocol version
|
|
87
|
-
"capabilities": {
|
|
88
|
-
"tools": {}
|
|
89
|
-
},
|
|
90
|
-
"serverInfo": {
|
|
91
|
-
"name": "nucleus-mcp",
|
|
92
|
-
"version": "1.0.0"
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
elif method == "notifications/initialized":
|
|
98
|
-
# No response needed for notification
|
|
99
|
-
return None
|
|
100
|
-
|
|
101
|
-
elif method == "tools/list":
|
|
102
|
-
# Create standard tools list
|
|
103
|
-
tools = [
|
|
104
|
-
{
|
|
105
|
-
"name": "lock_resource",
|
|
106
|
-
"description": "[HYPERVISOR] Lock a file/folder to prevent modification (Layer 4).",
|
|
107
|
-
"inputSchema": {
|
|
108
|
-
"type": "object",
|
|
109
|
-
"properties": {
|
|
110
|
-
"path": {"type": "string", "description": "Absolute path to lock"},
|
|
111
|
-
"reason": {"type": "string", "description": "Why is this being locked?"},
|
|
112
|
-
"agent_id": {"type": "string", "description": "Who is locking this?"}
|
|
113
|
-
},
|
|
114
|
-
"required": ["path"]
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
"name": "unlock_resource",
|
|
119
|
-
"description": "[HYPERVISOR] Unlock a resource.",
|
|
120
|
-
"inputSchema": {
|
|
121
|
-
"type": "object",
|
|
122
|
-
"properties": {
|
|
123
|
-
"path": {"type": "string", "description": "Absolute path to unlock"}
|
|
124
|
-
},
|
|
125
|
-
"required": ["path"]
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"name": "get_lock_metadata",
|
|
130
|
-
"description": "[HYPERVISOR] Retrieve lock metadata (Why/Who/When).",
|
|
131
|
-
"inputSchema": {
|
|
132
|
-
"type": "object",
|
|
133
|
-
"properties": {
|
|
134
|
-
"path": {"type": "string", "description": "Path to inspect"}
|
|
135
|
-
},
|
|
136
|
-
"required": ["path"]
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
"name": "watch_resource",
|
|
141
|
-
"description": "[HYPERVISOR] key file/folder monitoring (Layer 1).",
|
|
142
|
-
"inputSchema": {
|
|
143
|
-
"type": "object",
|
|
144
|
-
"properties": {
|
|
145
|
-
"path": {"type": "string", "description": "Path to watch"}
|
|
146
|
-
},
|
|
147
|
-
"required": ["path"]
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
"name": "hypervisor_status",
|
|
152
|
-
"description": "[HYPERVISOR] Reports the current security state of the Agent OS.",
|
|
153
|
-
"inputSchema": {
|
|
154
|
-
"type": "object",
|
|
155
|
-
"properties": {},
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
"name": "set_hypervisor_mode",
|
|
160
|
-
"description": "[HYPERVISOR] Switch Visual Context (Injector).",
|
|
161
|
-
"inputSchema": {
|
|
162
|
-
"type": "object",
|
|
163
|
-
"properties": {
|
|
164
|
-
"mode": {"type": "string", "enum": ["red", "blue", "reset"]}
|
|
165
|
-
},
|
|
166
|
-
"required": ["mode"]
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
"name": "brain_health",
|
|
171
|
-
"description": "Get comprehensive system health status.",
|
|
172
|
-
"inputSchema": {
|
|
173
|
-
"type": "object",
|
|
174
|
-
"properties": {}
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
"name": "brain_audit_log",
|
|
179
|
-
"description": "View the cryptographic interaction log for trust verification.",
|
|
180
|
-
"inputSchema": {
|
|
181
|
-
"type": "object",
|
|
182
|
-
"properties": {
|
|
183
|
-
"limit": {"type": "integer", "description": "Number of recent entries", "default": 20}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
"name": "brain_write_engram",
|
|
189
|
-
"description": "Write a long-term memory engram (learning/pattern).",
|
|
190
|
-
"inputSchema": {
|
|
191
|
-
"type": "object",
|
|
192
|
-
"properties": {
|
|
193
|
-
"key": {"type": "string", "description": "Unique identifier"},
|
|
194
|
-
"value": {"type": "string", "description": "Memory content"},
|
|
195
|
-
"context": {"type": "string", "enum": ["Feature", "Architecture", "Brand", "Strategy", "Decision"], "default": "Decision"},
|
|
196
|
-
"intensity": {"type": "integer", "minimum": 1, "maximum": 10, "default": 5}
|
|
197
|
-
},
|
|
198
|
-
"required": ["key", "value"]
|
|
199
|
-
}
|
|
200
|
-
},
|
|
201
|
-
{
|
|
202
|
-
"name": "brain_query_engrams",
|
|
203
|
-
"description": "Query context-aware memory engrams.",
|
|
204
|
-
"inputSchema": {
|
|
205
|
-
"type": "object",
|
|
206
|
-
"properties": {
|
|
207
|
-
"context": {"type": "string", "enum": ["Feature", "Architecture", "Brand", "Strategy", "Decision"]},
|
|
208
|
-
"min_intensity": {"type": "integer", "minimum": 1, "maximum": 10, "default": 1}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
"name": "brain_governance_status",
|
|
214
|
-
"description": "Get the current governance status and statistics.",
|
|
215
|
-
"inputSchema": {
|
|
216
|
-
"type": "object",
|
|
217
|
-
"properties": {}
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
{
|
|
221
|
-
"name": "brain_list_tasks",
|
|
222
|
-
"description": "List all tasks from the Brain (Task Ledger).",
|
|
223
|
-
"inputSchema": {
|
|
224
|
-
"type": "object",
|
|
225
|
-
"properties": {
|
|
226
|
-
"status": {"type": "string"},
|
|
227
|
-
"priority": {"type": "integer"},
|
|
228
|
-
"skill": {"type": "string"},
|
|
229
|
-
"claimed_by": {"type": "string"}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
"name": "brain_add_task",
|
|
235
|
-
"description": "Add a new task to the Brain.",
|
|
236
|
-
"inputSchema": {
|
|
237
|
-
"type": "object",
|
|
238
|
-
"properties": {
|
|
239
|
-
"description": {"type": "string"},
|
|
240
|
-
"priority": {"type": "integer"},
|
|
241
|
-
"blocked_by": {"type": "array", "items": {"type": "string"}},
|
|
242
|
-
"required_skills": {"type": "array", "items": {"type": "string"}}
|
|
243
|
-
},
|
|
244
|
-
"required": ["description"]
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
"name": "brain_update_task",
|
|
249
|
-
"description": "Update an existing task in the Brain.",
|
|
250
|
-
"inputSchema": {
|
|
251
|
-
"type": "object",
|
|
252
|
-
"properties": {
|
|
253
|
-
"task_id": {"type": "string"},
|
|
254
|
-
"status": {"type": "string"},
|
|
255
|
-
"description": {"type": "string"},
|
|
256
|
-
"priority": {"type": "integer"}
|
|
257
|
-
},
|
|
258
|
-
"required": ["task_id"]
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
"name": "brain_claim_task",
|
|
263
|
-
"description": "Claim a task for execution.",
|
|
264
|
-
"inputSchema": {
|
|
265
|
-
"type": "object",
|
|
266
|
-
"properties": {
|
|
267
|
-
"task_id": {"type": "string"},
|
|
268
|
-
"agent_id": {"type": "string"}
|
|
269
|
-
},
|
|
270
|
-
"required": ["task_id"]
|
|
271
|
-
}
|
|
272
|
-
},
|
|
273
|
-
{
|
|
274
|
-
"name": "brain_get_next_task",
|
|
275
|
-
"description": "Get the highest priority actionable task.",
|
|
276
|
-
"inputSchema": {
|
|
277
|
-
"type": "object",
|
|
278
|
-
"properties": {
|
|
279
|
-
"skills": {"type": "array", "items": {"type": "string"}}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
]
|
|
284
|
-
|
|
285
|
-
# --- MOUNTING TOOLS ---
|
|
286
|
-
tools.append({
|
|
287
|
-
"name": "brain_mount_server",
|
|
288
|
-
"description": "Mount an external MCP server (Recursive/Aggregator).",
|
|
289
|
-
"inputSchema": {
|
|
290
|
-
"type": "object",
|
|
291
|
-
"properties": {
|
|
292
|
-
"mount_id": {"type": "string", "description": "Unique ID for this mount"},
|
|
293
|
-
"transport": {"type": "string", "enum": ["stdio", "sse"], "default": "stdio"},
|
|
294
|
-
"command": {"type": "string", "description": "Executable for stdio"},
|
|
295
|
-
"args": {"type": "array", "items": {"type": "string"}, "description": "Arguments for stdio"},
|
|
296
|
-
"env": {"type": "object", "description": "Environment vars"},
|
|
297
|
-
"url": {"type": "string", "description": "URL for SSE"}
|
|
298
|
-
},
|
|
299
|
-
"required": ["mount_id"]
|
|
300
|
-
}
|
|
301
|
-
})
|
|
302
|
-
tools.append({
|
|
303
|
-
"name": "brain_unmount_server",
|
|
304
|
-
"description": "Unmount an external MCP server.",
|
|
305
|
-
"inputSchema": {
|
|
306
|
-
"type": "object",
|
|
307
|
-
"properties": {
|
|
308
|
-
"mount_id": {"type": "string"}
|
|
309
|
-
},
|
|
310
|
-
"required": ["mount_id"]
|
|
311
|
-
}
|
|
312
|
-
})
|
|
313
|
-
tools.append({
|
|
314
|
-
"name": "brain_list_mounts",
|
|
315
|
-
"description": "List all active mounted servers.",
|
|
316
|
-
"inputSchema": {"type": "object", "properties": {}}
|
|
317
|
-
})
|
|
318
|
-
tools.append({
|
|
319
|
-
"name": "brain_traverse_and_mount",
|
|
320
|
-
"description": "Recursively explore and mount downstream servers.",
|
|
321
|
-
"inputSchema": {
|
|
322
|
-
"type": "object",
|
|
323
|
-
"properties": {
|
|
324
|
-
"root_mount_id": {"type": "string"}
|
|
325
|
-
},
|
|
326
|
-
"required": ["root_mount_id"]
|
|
327
|
-
}
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
# Aggregate Tools from Mounts
|
|
331
|
-
try:
|
|
332
|
-
mounted_tools = await self.mounter.list_tools()
|
|
333
|
-
tools.extend(mounted_tools)
|
|
334
|
-
except Exception as e:
|
|
335
|
-
logger.error(f"Failed to list mounted tools: {e}")
|
|
336
|
-
|
|
337
|
-
return {
|
|
338
|
-
"jsonrpc": "2.0",
|
|
339
|
-
"id": msg_id,
|
|
340
|
-
"result": {
|
|
341
|
-
"tools": tools
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
elif method == "tools/call":
|
|
346
|
-
params = request.get("params", {})
|
|
347
|
-
name = params.get("name")
|
|
348
|
-
args = params.get("arguments", {})
|
|
349
|
-
|
|
350
|
-
try:
|
|
351
|
-
# --- MOUNTER DISPATCH ---
|
|
352
|
-
if ":" in name:
|
|
353
|
-
# Delegate to mounted server
|
|
354
|
-
result = await self.mounter.call_tool(name, args)
|
|
355
|
-
# Result is a ToolCallResult object from mcp SDK. We need to serialize it.
|
|
356
|
-
# The SDK usually returns an object with `content`.
|
|
357
|
-
# We need to adapt it to the dict format this server expects.
|
|
358
|
-
|
|
359
|
-
# Inspect result structure or assume it matches
|
|
360
|
-
content = []
|
|
361
|
-
if hasattr(result, "content"):
|
|
362
|
-
for item in result.content:
|
|
363
|
-
item_dict = item.model_dump() if hasattr(item, "model_dump") else item.__dict__
|
|
364
|
-
content.append(item_dict)
|
|
365
|
-
else:
|
|
366
|
-
content = [{"type": "text", "text": str(result)}]
|
|
367
|
-
|
|
368
|
-
return {
|
|
369
|
-
"jsonrpc": "2.0",
|
|
370
|
-
"id": msg_id,
|
|
371
|
-
"result": {
|
|
372
|
-
"content": content,
|
|
373
|
-
"isError": getattr(result, "isError", False)
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
# --- LOCAL DISPATCH ---
|
|
378
|
-
if name == "brain_mount_server":
|
|
379
|
-
res = await self.mounter.mount_server(
|
|
380
|
-
mount_id=args["mount_id"],
|
|
381
|
-
transport=args.get("transport", "stdio"),
|
|
382
|
-
command=args.get("command"),
|
|
383
|
-
args=args.get("args"),
|
|
384
|
-
env=args.get("env"),
|
|
385
|
-
url=args.get("url")
|
|
386
|
-
)
|
|
387
|
-
return {"jsonrpc": "2.0", "id": msg_id, "result": {"content": [{"type": "text", "text": json.dumps(res)}], "isError": False}}
|
|
388
|
-
|
|
389
|
-
elif name == "brain_unmount_server":
|
|
390
|
-
await self.mounter.unmount_server(args["mount_id"])
|
|
391
|
-
return {"jsonrpc": "2.0", "id": msg_id, "result": {"content": [{"type": "text", "text": "Unmounted"}], "isError": False}}
|
|
392
|
-
|
|
393
|
-
elif name == "brain_list_mounts":
|
|
394
|
-
res = await self.mounter.list_mounts()
|
|
395
|
-
return {"jsonrpc": "2.0", "id": msg_id, "result": {"content": [{"type": "text", "text": json.dumps(res, indent=2)}], "isError": False}}
|
|
396
|
-
|
|
397
|
-
elif name == "brain_traverse_and_mount":
|
|
398
|
-
res = await self.mounter.traverse_and_mount(args["root_mount_id"])
|
|
399
|
-
return {"jsonrpc": "2.0", "id": msg_id, "result": {"content": [{"type": "text", "text": json.dumps(res, indent=2)}], "isError": False}}
|
|
400
|
-
|
|
401
|
-
result = self.execute_tool(name, args)
|
|
402
|
-
return {
|
|
403
|
-
"jsonrpc": "2.0",
|
|
404
|
-
"id": msg_id,
|
|
405
|
-
"result": {
|
|
406
|
-
"content": [
|
|
407
|
-
{
|
|
408
|
-
"type": "text",
|
|
409
|
-
"text": str(result)
|
|
410
|
-
}
|
|
411
|
-
],
|
|
412
|
-
"isError": False
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
except Exception as e:
|
|
416
|
-
return {
|
|
417
|
-
"jsonrpc": "2.0",
|
|
418
|
-
"id": msg_id,
|
|
419
|
-
"error": {
|
|
420
|
-
"code": -32000,
|
|
421
|
-
"message": str(e)
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
def execute_tool(self, name: str, args: Dict[str, Any]) -> str:
|
|
426
|
-
if name == "lock_resource":
|
|
427
|
-
metadata = {}
|
|
428
|
-
if "reason" in args:
|
|
429
|
-
metadata["reason"] = args["reason"]
|
|
430
|
-
if "agent_id" in args:
|
|
431
|
-
metadata["agent_id"] = args["agent_id"]
|
|
432
|
-
|
|
433
|
-
self.locker.lock(args["path"], metadata=metadata)
|
|
434
|
-
return f"🔒 LOCKED: {args['path']}"
|
|
435
|
-
|
|
436
|
-
elif name == "unlock_resource":
|
|
437
|
-
self.locker.unlock(args["path"])
|
|
438
|
-
return f"🔓 UNLOCKED: {args['path']}"
|
|
439
|
-
|
|
440
|
-
elif name == "get_lock_metadata":
|
|
441
|
-
meta = self.locker.get_metadata(args["path"])
|
|
442
|
-
return json.dumps(meta, indent=2)
|
|
443
|
-
|
|
444
|
-
elif name == "watch_resource":
|
|
445
|
-
self.watchdog.protect(args["path"])
|
|
446
|
-
return f"👁️ WATCHING: {args['path']}"
|
|
447
|
-
|
|
448
|
-
elif name == "hypervisor_status":
|
|
449
|
-
status = []
|
|
450
|
-
status.append("🛡️ NUCLEUS HYPERVISOR v0.8.0 (God Mode / Python 3.9 Shim)")
|
|
451
|
-
status.append(f"👁️ Watchdog: {'Active' if self.watchdog.observer.is_alive() else 'Inactive'}")
|
|
452
|
-
status.append(f"🔒 Protected Paths: {len(self.watchdog.protected_paths)}")
|
|
453
|
-
return "\n".join(status)
|
|
454
|
-
|
|
455
|
-
elif name == "set_hypervisor_mode":
|
|
456
|
-
mode = args["mode"]
|
|
457
|
-
if mode == "red":
|
|
458
|
-
self.injector.inject_identity("RED TEAM", "#ff0000")
|
|
459
|
-
return "🔴 Hypervisor Mode: RED TEAM"
|
|
460
|
-
elif mode == "blue":
|
|
461
|
-
self.injector.inject_identity("BLUE TEAM", "#007acc")
|
|
462
|
-
return "🔵 Hypervisor Mode: BLUE TEAM"
|
|
463
|
-
elif mode == "reset":
|
|
464
|
-
self.injector.reset_identity()
|
|
465
|
-
return "⚪ Hypervisor Mode: RESET"
|
|
466
|
-
|
|
467
|
-
# --- GOVERNANCE & HEALTH ---
|
|
468
|
-
elif name == "brain_health":
|
|
469
|
-
try:
|
|
470
|
-
return json.dumps({
|
|
471
|
-
"status": "healthy",
|
|
472
|
-
"version": "1.0.0",
|
|
473
|
-
"tools_registered": 15,
|
|
474
|
-
"brain_path": str(self.brain_path),
|
|
475
|
-
"uptime_seconds": int(time.time() - START_TIME),
|
|
476
|
-
"python_version": sys.version.split()[0]
|
|
477
|
-
}, indent=2)
|
|
478
|
-
except Exception as e:
|
|
479
|
-
return json.dumps({"status": "unhealthy", "error": str(e)})
|
|
480
|
-
|
|
481
|
-
elif name == "brain_audit_log":
|
|
482
|
-
return self._audit_log_impl(args.get("limit", 20))
|
|
483
|
-
|
|
484
|
-
elif name == "brain_governance_status":
|
|
485
|
-
return self._governance_status_impl()
|
|
486
|
-
|
|
487
|
-
elif name == "brain_write_engram":
|
|
488
|
-
return self._write_engram_impl(
|
|
489
|
-
args["key"],
|
|
490
|
-
args["value"],
|
|
491
|
-
args.get("context", "Decision"),
|
|
492
|
-
args.get("intensity", 5)
|
|
493
|
-
)
|
|
494
|
-
|
|
495
|
-
elif name == "brain_query_engrams":
|
|
496
|
-
return self._query_engrams_impl(
|
|
497
|
-
args.get("context"),
|
|
498
|
-
args.get("min_intensity", 1)
|
|
499
|
-
)
|
|
500
|
-
|
|
501
|
-
# --- TASK TOOLS ---
|
|
502
|
-
elif name == "brain_list_tasks":
|
|
503
|
-
return json.dumps(_list_tasks(
|
|
504
|
-
status=args.get("status"),
|
|
505
|
-
priority=args.get("priority"),
|
|
506
|
-
skill=args.get("skill"),
|
|
507
|
-
claimed_by=args.get("claimed_by")
|
|
508
|
-
), indent=2)
|
|
509
|
-
|
|
510
|
-
elif name == "brain_add_task":
|
|
511
|
-
return json.dumps(_add_task(
|
|
512
|
-
description=args.get("description"),
|
|
513
|
-
priority=args.get("priority", 3),
|
|
514
|
-
blocked_by=args.get("blocked_by"),
|
|
515
|
-
required_skills=args.get("required_skills"),
|
|
516
|
-
source="hypervisor"
|
|
517
|
-
), indent=2)
|
|
518
|
-
|
|
519
|
-
elif name == "brain_update_task":
|
|
520
|
-
updates = {k: v for k, v in args.items() if k != "task_id"}
|
|
521
|
-
return json.dumps(_update_task(
|
|
522
|
-
task_id=args.get("task_id"),
|
|
523
|
-
updates=updates
|
|
524
|
-
), indent=2)
|
|
525
|
-
|
|
526
|
-
elif name == "brain_claim_task":
|
|
527
|
-
return json.dumps(_claim_task(
|
|
528
|
-
task_id=args.get("task_id"),
|
|
529
|
-
agent_id=args.get("agent_id", "hypervisor_agent")
|
|
530
|
-
), indent=2)
|
|
531
|
-
|
|
532
|
-
elif name == "brain_get_next_task":
|
|
533
|
-
return json.dumps(_get_next_task(
|
|
534
|
-
skills=args.get("skills", [])
|
|
535
|
-
), indent=2)
|
|
536
|
-
|
|
537
|
-
raise ValueError(f"Unknown tool: {name}")
|
|
538
|
-
|
|
539
|
-
def _audit_log_impl(self, limit: int) -> str:
|
|
540
|
-
try:
|
|
541
|
-
log_path = self.brain_path / "ledger" / "interaction_log.jsonl"
|
|
542
|
-
if not log_path.exists():
|
|
543
|
-
return make_response(True, data={"entries": [], "count": 0, "message": "No log found."})
|
|
544
|
-
|
|
545
|
-
entries = []
|
|
546
|
-
with open(log_path, "r") as f:
|
|
547
|
-
for line in f:
|
|
548
|
-
if line.strip():
|
|
549
|
-
entries.append(json.loads(line))
|
|
550
|
-
|
|
551
|
-
recent = entries[-limit:] if len(entries) > limit else entries
|
|
552
|
-
recent.reverse()
|
|
553
|
-
return make_response(True, data={"entries": recent, "count": len(recent), "total": len(entries)})
|
|
554
|
-
except Exception as e:
|
|
555
|
-
return make_response(False, error=str(e))
|
|
556
|
-
|
|
557
|
-
def _governance_status_impl(self) -> str:
|
|
558
|
-
try:
|
|
559
|
-
audit_path = self.brain_path / "ledger" / "interaction_log.jsonl"
|
|
560
|
-
audit_count = 0
|
|
561
|
-
if audit_path.exists():
|
|
562
|
-
with open(audit_path, "r") as f:
|
|
563
|
-
audit_count = sum(1 for line in f if line.strip())
|
|
564
|
-
|
|
565
|
-
engram_path = self.brain_path / "engrams" / "ledger.jsonl"
|
|
566
|
-
engram_count = 0
|
|
567
|
-
if engram_path.exists():
|
|
568
|
-
with open(engram_path, "r") as f:
|
|
569
|
-
engram_count = sum(1 for line in f if line.strip())
|
|
570
|
-
|
|
571
|
-
governance = {
|
|
572
|
-
"policies": {"default_deny": True, "isolation_boundaries": True, "immutable_audit": True},
|
|
573
|
-
"statistics": {"audit_log_entries": audit_count, "engram_count": engram_count},
|
|
574
|
-
"status": "ENFORCED"
|
|
575
|
-
}
|
|
576
|
-
return make_response(True, data=governance)
|
|
577
|
-
except Exception as e:
|
|
578
|
-
return make_response(False, error=str(e))
|
|
579
|
-
|
|
580
|
-
def _write_engram_impl(self, key: str, value: str, context: str, intensity: int) -> str:
|
|
581
|
-
try:
|
|
582
|
-
if not re.match(r"^[a-zA-Z0-9_.-]+$", key):
|
|
583
|
-
return make_response(False, error="Invalid key characters")
|
|
584
|
-
|
|
585
|
-
engram_path = self.brain_path / "engrams" / "ledger.jsonl"
|
|
586
|
-
engram_path.parent.mkdir(parents=True, exist_ok=True)
|
|
587
|
-
|
|
588
|
-
engram = {
|
|
589
|
-
"key": key, "value": value, "context": context,
|
|
590
|
-
"intensity": intensity, "timestamp": datetime.now().isoformat()
|
|
591
|
-
}
|
|
592
|
-
with open(engram_path, "a") as f:
|
|
593
|
-
f.write(json.dumps(engram) + "\n")
|
|
594
|
-
|
|
595
|
-
return make_response(True, data={"engram": engram, "message": f"Engram '{key}' written."})
|
|
596
|
-
except Exception as e:
|
|
597
|
-
return make_response(False, error=str(e))
|
|
598
|
-
|
|
599
|
-
def _query_engrams_impl(self, context: Optional[str], min_intensity: int) -> str:
|
|
600
|
-
try:
|
|
601
|
-
engram_path = self.brain_path / "engrams" / "ledger.jsonl"
|
|
602
|
-
if not engram_path.exists():
|
|
603
|
-
return make_response(True, data={"engrams": [], "count": 0})
|
|
604
|
-
|
|
605
|
-
engrams = []
|
|
606
|
-
with open(engram_path, "r") as f:
|
|
607
|
-
for line in f:
|
|
608
|
-
if line.strip():
|
|
609
|
-
e = json.loads(line)
|
|
610
|
-
if context and e.get("context", "").lower() != context.lower():
|
|
611
|
-
continue
|
|
612
|
-
if e.get("intensity", 5) < min_intensity:
|
|
613
|
-
continue
|
|
614
|
-
engrams.append(e)
|
|
615
|
-
|
|
616
|
-
engrams.sort(key=lambda x: x.get("intensity", 5), reverse=True)
|
|
617
|
-
return make_response(True, data={"engrams": engrams, "count": len(engrams)})
|
|
618
|
-
except Exception as e:
|
|
619
|
-
return make_response(False, error=str(e))
|
|
620
|
-
|
|
621
|
-
def main():
|
|
622
|
-
sys.stderr.write("DEBUG: STDIO_SERVER MAIN START\n")
|
|
623
|
-
sys.stderr.flush()
|
|
624
|
-
server = StdioServer()
|
|
625
|
-
sys.stderr.write("DEBUG: STDIO_SERVER AFTER INIT\n")
|
|
626
|
-
sys.stderr.flush()
|
|
627
|
-
sys.stderr.write("Nucleus Sovereign Control Plane (Stdio Mode)\n")
|
|
628
|
-
sys.stderr.flush()
|
|
629
|
-
# Run async main loop
|
|
630
|
-
asyncio.run(server.run())
|
|
631
|
-
|
|
632
|
-
if __name__ == "__main__":
|
|
633
|
-
main()
|