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,243 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Nucleus Tool Tier System - Registry Bloat Solution
|
|
3
|
-
|
|
4
|
-
Solves the "137 tools crash LLM client" problem by organizing tools into tiers:
|
|
5
|
-
- Tier 0 (LAUNCH): 5 essential tools for nucleusos.dev demo
|
|
6
|
-
- Tier 1 (CORE): 20 standard operation tools
|
|
7
|
-
- Tier 2 (ADVANCED): All 137 tools
|
|
8
|
-
|
|
9
|
-
Set NUCLEUS_TOOL_TIER environment variable to control which tier is active:
|
|
10
|
-
- "0" or "launch": Only Tier 0 tools (default for website)
|
|
11
|
-
- "1" or "core": Tier 0 + Tier 1 tools
|
|
12
|
-
- "2" or "advanced" or "all": All tools
|
|
13
|
-
|
|
14
|
-
Author: Nucleus Team
|
|
15
|
-
Version: 0.6.0
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
import os
|
|
19
|
-
from typing import Set, Dict, Any
|
|
20
|
-
|
|
21
|
-
# =============================================================================
|
|
22
|
-
# TIER DEFINITIONS
|
|
23
|
-
# =============================================================================
|
|
24
|
-
|
|
25
|
-
TIER_0_LAUNCH: Set[str] = {
|
|
26
|
-
# The "Govern Your Agents in 60 Seconds" story
|
|
27
|
-
"brain_write_engram", # Persist a memory
|
|
28
|
-
"brain_query_engrams", # Retrieve memories
|
|
29
|
-
"brain_search_engrams", # Substring search (v0.6.0)
|
|
30
|
-
"brain_audit_log", # Trust verification (SHA-256 ledger)
|
|
31
|
-
"brain_mount_server", # Recursive aggregation demo (TEASER ONLY - Limited)
|
|
32
|
-
# Meta tools
|
|
33
|
-
"brain_version", # Version check
|
|
34
|
-
"brain_health", # Health check
|
|
35
|
-
"brain_list_tools", # Discover available tools
|
|
36
|
-
# Governance Demo Tools
|
|
37
|
-
"nucleus_list_directory", # Demo A: Inspect environment
|
|
38
|
-
"nucleus_delete_file", # Demo A: Test protection
|
|
39
|
-
"lock_resource", # Demo A: Block modification
|
|
40
|
-
"unlock_resource", # Demo A: Allow modification
|
|
41
|
-
"hypervisor_status", # Demo A: Status check
|
|
42
|
-
"watch_resource", # Demo A: Monitor changes
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
TIER_1_CORE: Set[str] = {
|
|
46
|
-
# Task Management
|
|
47
|
-
"brain_list_tasks",
|
|
48
|
-
"brain_get_next_task",
|
|
49
|
-
"brain_add_task",
|
|
50
|
-
"brain_update_task",
|
|
51
|
-
"brain_claim_task",
|
|
52
|
-
# Orchestration
|
|
53
|
-
"brain_orchestrate",
|
|
54
|
-
"brain_spawn_agent",
|
|
55
|
-
"brain_slot_complete",
|
|
56
|
-
# State & Status
|
|
57
|
-
"brain_get_state",
|
|
58
|
-
"brain_update_state",
|
|
59
|
-
"brain_dashboard",
|
|
60
|
-
"brain_status_dashboard",
|
|
61
|
-
# DSoR
|
|
62
|
-
"brain_dsor_status",
|
|
63
|
-
"brain_list_decisions",
|
|
64
|
-
"brain_metering_summary",
|
|
65
|
-
"brain_ipc_tokens",
|
|
66
|
-
# Sessions
|
|
67
|
-
"brain_session_start",
|
|
68
|
-
"brain_save_session",
|
|
69
|
-
"brain_list_sessions",
|
|
70
|
-
# Memory
|
|
71
|
-
"brain_read_memory",
|
|
72
|
-
"brain_search_memory",
|
|
73
|
-
# Multi-Agent Sync (v0.7.0)
|
|
74
|
-
"brain_sync_status",
|
|
75
|
-
"brain_sync_now",
|
|
76
|
-
"brain_sync_auto",
|
|
77
|
-
"brain_sync_auto",
|
|
78
|
-
"brain_identify_agent",
|
|
79
|
-
# Hypervisor (v0.8.0)
|
|
80
|
-
"lock_resource",
|
|
81
|
-
"unlock_resource",
|
|
82
|
-
"watch_resource",
|
|
83
|
-
"hypervisor_status",
|
|
84
|
-
"set_hypervisor_mode",
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
TIER_2_ADVANCED: Set[str] = {
|
|
88
|
-
# Federation
|
|
89
|
-
"brain_federation_status",
|
|
90
|
-
"brain_federation_join",
|
|
91
|
-
"brain_federation_leave",
|
|
92
|
-
"brain_federation_peers",
|
|
93
|
-
"brain_federation_sync",
|
|
94
|
-
"brain_federation_route",
|
|
95
|
-
"brain_federation_health",
|
|
96
|
-
"brain_federation_dsor_status",
|
|
97
|
-
"brain_routing_decisions",
|
|
98
|
-
# Depth Management
|
|
99
|
-
"brain_depth_map",
|
|
100
|
-
"brain_depth_push",
|
|
101
|
-
"brain_depth_pop",
|
|
102
|
-
"brain_depth_show",
|
|
103
|
-
"brain_depth_reset",
|
|
104
|
-
"brain_depth_set_max",
|
|
105
|
-
# Autopilot
|
|
106
|
-
"brain_autopilot_sprint",
|
|
107
|
-
"brain_autopilot_sprint_v2",
|
|
108
|
-
"brain_halt_sprint",
|
|
109
|
-
"brain_resume_sprint",
|
|
110
|
-
# Ingestion
|
|
111
|
-
"brain_ingest_tasks",
|
|
112
|
-
"brain_ingestion_stats",
|
|
113
|
-
"brain_rollback_ingestion",
|
|
114
|
-
"brain_import_tasks_from_jsonl",
|
|
115
|
-
# Features
|
|
116
|
-
"brain_add_feature",
|
|
117
|
-
"brain_get_feature",
|
|
118
|
-
"brain_list_features",
|
|
119
|
-
"brain_update_feature",
|
|
120
|
-
"brain_search_features",
|
|
121
|
-
# Artifacts
|
|
122
|
-
"brain_write_artifact",
|
|
123
|
-
"brain_read_artifact",
|
|
124
|
-
"brain_list_artifacts",
|
|
125
|
-
# Proofs
|
|
126
|
-
"brain_generate_proof",
|
|
127
|
-
"brain_get_proof",
|
|
128
|
-
"brain_list_proofs",
|
|
129
|
-
# Everything else is implicitly Tier 2
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
# =============================================================================
|
|
133
|
-
# TIER RESOLUTION
|
|
134
|
-
# =============================================================================
|
|
135
|
-
|
|
136
|
-
# Global cache for the active tier to avoid repeated lookups during import
|
|
137
|
-
_ACTIVE_TIER_CACHE = None
|
|
138
|
-
|
|
139
|
-
def get_active_tier() -> int:
|
|
140
|
-
"""Determine the active tier based on environment variables."""
|
|
141
|
-
global _ACTIVE_TIER_CACHE
|
|
142
|
-
if _ACTIVE_TIER_CACHE is not None:
|
|
143
|
-
return _ACTIVE_TIER_CACHE
|
|
144
|
-
|
|
145
|
-
# Security through Obscurity (v0.6.0 Friction)
|
|
146
|
-
# Prevents casual users from flipping a simple '1' switch.
|
|
147
|
-
# Hackers who read source will find this. That is acceptable marketing.
|
|
148
|
-
beta_token = os.environ.get("NUCLEUS_BETA_TOKEN", "").strip()
|
|
149
|
-
|
|
150
|
-
if beta_token == "sovereign-launch-alpha":
|
|
151
|
-
_ACTIVE_TIER_CACHE = 1 # Unlock Manager Suite
|
|
152
|
-
elif beta_token == "titan-sovereign-godmode":
|
|
153
|
-
_ACTIVE_TIER_CACHE = 2 # Unlock Everything
|
|
154
|
-
else:
|
|
155
|
-
_ACTIVE_TIER_CACHE = 0 # Default to Journal Mode
|
|
156
|
-
|
|
157
|
-
return _ACTIVE_TIER_CACHE
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
def get_allowed_tools() -> Set[str]:
|
|
161
|
-
"""Get the set of tool names allowed for the current tier."""
|
|
162
|
-
tier = get_active_tier()
|
|
163
|
-
|
|
164
|
-
if tier == 0:
|
|
165
|
-
return TIER_0_LAUNCH.copy()
|
|
166
|
-
elif tier == 1:
|
|
167
|
-
return TIER_0_LAUNCH | TIER_1_CORE
|
|
168
|
-
else:
|
|
169
|
-
# Tier 2 allows all tools
|
|
170
|
-
return None # None means no filtering
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def is_tool_allowed(tool_name: str) -> bool:
|
|
174
|
-
"""Check if a specific tool is allowed in the current tier."""
|
|
175
|
-
allowed = get_allowed_tools()
|
|
176
|
-
|
|
177
|
-
if allowed is None:
|
|
178
|
-
return True # Tier 2 allows all
|
|
179
|
-
|
|
180
|
-
return tool_name in allowed
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def get_tier_info() -> Dict[str, Any]:
|
|
184
|
-
"""Get information about current tier configuration."""
|
|
185
|
-
tier = get_active_tier()
|
|
186
|
-
allowed = get_allowed_tools()
|
|
187
|
-
|
|
188
|
-
tier_names = {0: "LAUNCH", 1: "CORE", 2: "ADVANCED"}
|
|
189
|
-
|
|
190
|
-
return {
|
|
191
|
-
"active_tier": tier,
|
|
192
|
-
"tier_name": tier_names.get(tier, "UNKNOWN"),
|
|
193
|
-
"tools_allowed": len(allowed) if allowed else "ALL",
|
|
194
|
-
"tier_0_count": len(TIER_0_LAUNCH),
|
|
195
|
-
"tier_1_count": len(TIER_1_CORE),
|
|
196
|
-
"tier_2_count": len(TIER_2_ADVANCED),
|
|
197
|
-
"env_var": "NUCLEUS_TOOL_TIER",
|
|
198
|
-
"current_value": os.environ.get("NUCLEUS_TOOL_TIER", "0"),
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
# =============================================================================
|
|
203
|
-
# TOOL REGISTRATION FILTER
|
|
204
|
-
# =============================================================================
|
|
205
|
-
|
|
206
|
-
class TierFilteredToolManager:
|
|
207
|
-
"""
|
|
208
|
-
Manages tool registration with tier filtering.
|
|
209
|
-
|
|
210
|
-
Usage:
|
|
211
|
-
manager = TierFilteredToolManager()
|
|
212
|
-
|
|
213
|
-
@manager.register("brain_my_tool")
|
|
214
|
-
def brain_my_tool():
|
|
215
|
-
pass
|
|
216
|
-
"""
|
|
217
|
-
|
|
218
|
-
def __init__(self):
|
|
219
|
-
self.registered_tools: Set[str] = set()
|
|
220
|
-
self.filtered_tools: Set[str] = set()
|
|
221
|
-
|
|
222
|
-
def should_register(self, tool_name: str) -> bool:
|
|
223
|
-
"""Check if tool should be registered based on tier."""
|
|
224
|
-
allowed = is_tool_allowed(tool_name)
|
|
225
|
-
|
|
226
|
-
if allowed:
|
|
227
|
-
self.registered_tools.add(tool_name)
|
|
228
|
-
else:
|
|
229
|
-
self.filtered_tools.add(tool_name)
|
|
230
|
-
|
|
231
|
-
return allowed
|
|
232
|
-
|
|
233
|
-
def get_stats(self) -> Dict[str, Any]:
|
|
234
|
-
"""Get registration statistics."""
|
|
235
|
-
return {
|
|
236
|
-
"registered": len(self.registered_tools),
|
|
237
|
-
"filtered": len(self.filtered_tools),
|
|
238
|
-
"tier_info": get_tier_info(),
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# Global instance for use in __init__.py
|
|
243
|
-
tier_manager = TierFilteredToolManager()
|
package/tests/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""Nucleus MCP Tests"""
|
package/tests/conftest.py
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import pytest
|
|
3
|
-
import os
|
|
4
|
-
import tempfile
|
|
5
|
-
import json
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from mcp_server_nucleus.runtime.common import get_brain_path
|
|
8
|
-
|
|
9
|
-
@pytest.fixture
|
|
10
|
-
def temp_brain():
|
|
11
|
-
"""Create a temporary brain directory for testing."""
|
|
12
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
13
|
-
old_brain = os.environ.get("NUCLEAR_BRAIN_PATH")
|
|
14
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
15
|
-
|
|
16
|
-
# Initialize structure
|
|
17
|
-
brain_path = Path(tmpdir)
|
|
18
|
-
(brain_path / "engrams").mkdir(parents=True, exist_ok=True)
|
|
19
|
-
(brain_path / "ledger").mkdir(parents=True, exist_ok=True)
|
|
20
|
-
|
|
21
|
-
yield brain_path
|
|
22
|
-
|
|
23
|
-
if old_brain:
|
|
24
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = old_brain
|
|
25
|
-
else:
|
|
26
|
-
del os.environ["NUCLEAR_BRAIN_PATH"]
|
|
27
|
-
|
|
28
|
-
@pytest.fixture
|
|
29
|
-
def sample_engrams(temp_brain):
|
|
30
|
-
"""Seed the brain with sample engrams."""
|
|
31
|
-
engram_path = temp_brain / "engrams" / "ledger.jsonl"
|
|
32
|
-
engrams = [
|
|
33
|
-
{"key": "db_choice", "value": "PostgreSQL", "context": "Architecture", "intensity": 8},
|
|
34
|
-
{"key": "ui_theme", "value": "Dark Mode", "context": "UI", "intensity": 5},
|
|
35
|
-
{"key": "api_key", "value": "SECRET", "context": "Security", "intensity": 10},
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
with open(engram_path, "w") as f:
|
|
39
|
-
for e in engrams:
|
|
40
|
-
f.write(json.dumps(e) + "\n")
|
|
41
|
-
|
|
42
|
-
return engrams
|
package/tests/test_core.py
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Core tests for Nucleus MCP - Updated for v1.0.5 API
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import json
|
|
6
|
-
import tempfile
|
|
7
|
-
import os
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
import pytest
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TestBrainPath:
|
|
14
|
-
"""Tests for brain path functionality."""
|
|
15
|
-
|
|
16
|
-
def test_get_brain_path_requires_env(self):
|
|
17
|
-
"""Test that brain path requires env var (v1.0+ behavior)."""
|
|
18
|
-
from mcp_server_nucleus import get_brain_path
|
|
19
|
-
|
|
20
|
-
# Clear env var
|
|
21
|
-
old_val = os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
22
|
-
|
|
23
|
-
try:
|
|
24
|
-
with pytest.raises(ValueError):
|
|
25
|
-
get_brain_path()
|
|
26
|
-
finally:
|
|
27
|
-
if old_val:
|
|
28
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = old_val
|
|
29
|
-
|
|
30
|
-
def test_get_brain_path_from_env(self):
|
|
31
|
-
"""Test brain path from environment variable."""
|
|
32
|
-
from mcp_server_nucleus import get_brain_path
|
|
33
|
-
|
|
34
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
35
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
36
|
-
|
|
37
|
-
try:
|
|
38
|
-
path = get_brain_path()
|
|
39
|
-
assert path == Path(tmpdir)
|
|
40
|
-
assert path.exists()
|
|
41
|
-
finally:
|
|
42
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class TestMakeResponse:
|
|
46
|
-
"""Tests for response formatting."""
|
|
47
|
-
|
|
48
|
-
def test_make_response_success(self):
|
|
49
|
-
"""Test successful response format."""
|
|
50
|
-
from mcp_server_nucleus import make_response
|
|
51
|
-
|
|
52
|
-
response = make_response(True, data={"key": "value"})
|
|
53
|
-
data = json.loads(response)
|
|
54
|
-
|
|
55
|
-
assert data["success"] is True
|
|
56
|
-
assert data["data"]["key"] == "value"
|
|
57
|
-
assert "timestamp" in data
|
|
58
|
-
|
|
59
|
-
def test_make_response_failure(self):
|
|
60
|
-
"""Test failure response format."""
|
|
61
|
-
from mcp_server_nucleus import make_response
|
|
62
|
-
|
|
63
|
-
response = make_response(False, error="Error message")
|
|
64
|
-
data = json.loads(response)
|
|
65
|
-
|
|
66
|
-
assert data["success"] is False
|
|
67
|
-
assert data["error"] == "Error message"
|
|
68
|
-
|
|
69
|
-
def test_make_response_with_error_code(self):
|
|
70
|
-
"""Test response with error code."""
|
|
71
|
-
from mcp_server_nucleus import make_response
|
|
72
|
-
|
|
73
|
-
response = make_response(False, error="Not found", error_code="ERR_NOT_FOUND")
|
|
74
|
-
data = json.loads(response)
|
|
75
|
-
|
|
76
|
-
assert data["error_code"] == "ERR_NOT_FOUND"
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class TestStateManagement:
|
|
80
|
-
"""Tests for state management."""
|
|
81
|
-
|
|
82
|
-
def test_get_state_empty(self):
|
|
83
|
-
"""Test getting state when empty."""
|
|
84
|
-
from mcp_server_nucleus import _get_state
|
|
85
|
-
|
|
86
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
87
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
88
|
-
|
|
89
|
-
try:
|
|
90
|
-
state = _get_state()
|
|
91
|
-
assert state == {}
|
|
92
|
-
finally:
|
|
93
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
94
|
-
|
|
95
|
-
def test_update_state(self):
|
|
96
|
-
"""Test updating state."""
|
|
97
|
-
from mcp_server_nucleus import _update_state, _get_state
|
|
98
|
-
|
|
99
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
100
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
101
|
-
# Create ledger directory
|
|
102
|
-
Path(tmpdir, "ledger").mkdir(parents=True, exist_ok=True)
|
|
103
|
-
|
|
104
|
-
try:
|
|
105
|
-
result = _update_state({"test_key": "test_value"})
|
|
106
|
-
assert "successfully" in result.lower() or "error" not in result.lower()
|
|
107
|
-
|
|
108
|
-
state = _get_state()
|
|
109
|
-
assert state.get("test_key") == "test_value"
|
|
110
|
-
finally:
|
|
111
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
class TestEventEmission:
|
|
115
|
-
"""Tests for event logging."""
|
|
116
|
-
|
|
117
|
-
def test_emit_event(self):
|
|
118
|
-
"""Test event emission."""
|
|
119
|
-
from mcp_server_nucleus import _emit_event
|
|
120
|
-
|
|
121
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
122
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
123
|
-
# Create ledger directory (required for event writing)
|
|
124
|
-
Path(tmpdir, "ledger").mkdir(parents=True, exist_ok=True)
|
|
125
|
-
|
|
126
|
-
try:
|
|
127
|
-
_emit_event("TEST_EVENT", "test_emitter", {"key": "value"})
|
|
128
|
-
|
|
129
|
-
events_path = Path(tmpdir) / "ledger" / "events.jsonl"
|
|
130
|
-
assert events_path.exists()
|
|
131
|
-
|
|
132
|
-
with open(events_path) as f:
|
|
133
|
-
line = f.readline()
|
|
134
|
-
event = json.loads(line)
|
|
135
|
-
|
|
136
|
-
assert event["type"] == "TEST_EVENT"
|
|
137
|
-
assert event["data"]["key"] == "value"
|
|
138
|
-
finally:
|
|
139
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
class TestEngramTools:
|
|
143
|
-
"""Tests for engram (memory) tools."""
|
|
144
|
-
|
|
145
|
-
def test_write_and_query_engram(self):
|
|
146
|
-
"""Test writing and querying engrams."""
|
|
147
|
-
from mcp_server_nucleus import _brain_write_engram_impl, _brain_query_engrams_impl
|
|
148
|
-
|
|
149
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
150
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
151
|
-
|
|
152
|
-
try:
|
|
153
|
-
# Write an engram (context must be valid: Feature, Architecture, Brand, Strategy, Decision)
|
|
154
|
-
result = _brain_write_engram_impl(
|
|
155
|
-
key="test_key",
|
|
156
|
-
value="Test knowledge",
|
|
157
|
-
context="Decision",
|
|
158
|
-
intensity=5
|
|
159
|
-
)
|
|
160
|
-
data = json.loads(result)
|
|
161
|
-
assert data["success"] is True
|
|
162
|
-
assert "engram" in data["data"]
|
|
163
|
-
assert data["data"]["engram"]["key"] == "test_key"
|
|
164
|
-
|
|
165
|
-
# Query engrams by context
|
|
166
|
-
result = _brain_query_engrams_impl(context="Decision", min_intensity=1)
|
|
167
|
-
data = json.loads(result)
|
|
168
|
-
assert data["success"] is True
|
|
169
|
-
assert len(data["data"]["engrams"]) > 0
|
|
170
|
-
assert "Test knowledge" in data["data"]["engrams"][0]["value"]
|
|
171
|
-
finally:
|
|
172
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class TestSyncTools:
|
|
176
|
-
"""Tests for sync functionality."""
|
|
177
|
-
|
|
178
|
-
def test_identify_agent(self):
|
|
179
|
-
"""Test agent identification."""
|
|
180
|
-
from mcp_server_nucleus import brain_identify_agent
|
|
181
|
-
|
|
182
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
183
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
184
|
-
|
|
185
|
-
try:
|
|
186
|
-
# Call the public function directly
|
|
187
|
-
result = brain_identify_agent("test_agent", "cursor")
|
|
188
|
-
data = json.loads(result)
|
|
189
|
-
|
|
190
|
-
# v1.0.5 returns flat structure with agent_id
|
|
191
|
-
assert data["agent_id"] == "test_agent"
|
|
192
|
-
assert data["environment"] == "cursor"
|
|
193
|
-
finally:
|
|
194
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
195
|
-
|
|
196
|
-
def test_sync_now(self):
|
|
197
|
-
"""Test manual sync."""
|
|
198
|
-
from mcp_server_nucleus import brain_sync_now
|
|
199
|
-
|
|
200
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
201
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
202
|
-
|
|
203
|
-
try:
|
|
204
|
-
result = brain_sync_now()
|
|
205
|
-
data = json.loads(result)
|
|
206
|
-
|
|
207
|
-
# Returns error when sync not enabled (expected behavior)
|
|
208
|
-
assert "error" in data or "status" in data or "success" in data
|
|
209
|
-
finally:
|
|
210
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
class TestHealthCheck:
|
|
214
|
-
"""Tests for health check."""
|
|
215
|
-
|
|
216
|
-
def test_brain_health(self):
|
|
217
|
-
"""Test brain health check."""
|
|
218
|
-
from mcp_server_nucleus import _brain_health_impl
|
|
219
|
-
|
|
220
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
221
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
222
|
-
|
|
223
|
-
try:
|
|
224
|
-
result = _brain_health_impl()
|
|
225
|
-
data = json.loads(result)
|
|
226
|
-
|
|
227
|
-
# v1.0.5 returns flat structure with status
|
|
228
|
-
assert "status" in data
|
|
229
|
-
assert "uptime_seconds" in data
|
|
230
|
-
finally:
|
|
231
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if __name__ == "__main__":
|
|
235
|
-
pytest.main([__file__, "-v"])
|
package/tests/test_search.py
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Search tests for Nucleus MCP - Updated for v1.0.5 API
|
|
3
|
-
|
|
4
|
-
Note: The current API queries by context and min_intensity, not by keyword.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import json
|
|
8
|
-
import os
|
|
9
|
-
import tempfile
|
|
10
|
-
|
|
11
|
-
import pytest
|
|
12
|
-
from mcp_server_nucleus import _brain_query_engrams_impl, _brain_write_engram_impl
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@pytest.fixture
|
|
16
|
-
def temp_brain():
|
|
17
|
-
"""Create a temporary brain directory."""
|
|
18
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
19
|
-
os.environ["NUCLEAR_BRAIN_PATH"] = tmpdir
|
|
20
|
-
yield tmpdir
|
|
21
|
-
os.environ.pop("NUCLEAR_BRAIN_PATH", None)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@pytest.fixture
|
|
25
|
-
def sample_engrams(temp_brain):
|
|
26
|
-
"""Create sample engrams for testing."""
|
|
27
|
-
engrams = [
|
|
28
|
-
("db_choice", "PostgreSQL for ACID compliance", "Architecture", 8),
|
|
29
|
-
("api_key", "SECRET_KEY_12345", "Decision", 5),
|
|
30
|
-
("design_pattern", "Use factory pattern", "Architecture", 6),
|
|
31
|
-
]
|
|
32
|
-
for key, value, context, intensity in engrams:
|
|
33
|
-
_brain_write_engram_impl(key, value, context, intensity)
|
|
34
|
-
return engrams
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def test_brain_query_by_context(temp_brain, sample_engrams):
|
|
38
|
-
"""Test querying engrams by context."""
|
|
39
|
-
|
|
40
|
-
# Query Architecture context
|
|
41
|
-
res_str = _brain_query_engrams_impl(context="Architecture", min_intensity=1)
|
|
42
|
-
res = json.loads(res_str)
|
|
43
|
-
assert res["success"] is True
|
|
44
|
-
assert res["data"]["count"] == 2 # db_choice and design_pattern
|
|
45
|
-
|
|
46
|
-
# Query Decision context
|
|
47
|
-
res_str = _brain_query_engrams_impl(context="Decision", min_intensity=1)
|
|
48
|
-
res = json.loads(res_str)
|
|
49
|
-
assert res["success"] is True
|
|
50
|
-
assert res["data"]["count"] == 1 # api_key
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def test_brain_query_by_intensity(temp_brain, sample_engrams):
|
|
54
|
-
"""Test filtering engrams by minimum intensity."""
|
|
55
|
-
|
|
56
|
-
# High intensity only
|
|
57
|
-
res_str = _brain_query_engrams_impl(context="Architecture", min_intensity=7)
|
|
58
|
-
res = json.loads(res_str)
|
|
59
|
-
assert res["success"] is True
|
|
60
|
-
assert res["data"]["count"] == 1 # only db_choice has intensity 8
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def test_brain_query_all(temp_brain, sample_engrams):
|
|
64
|
-
"""Test querying all engrams (no context filter)."""
|
|
65
|
-
|
|
66
|
-
res_str = _brain_query_engrams_impl(context=None, min_intensity=1)
|
|
67
|
-
res = json.loads(res_str)
|
|
68
|
-
assert res["success"] is True
|
|
69
|
-
assert res["data"]["count"] == 3 # all engrams
|