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.
Files changed (135) hide show
  1. package/package.json +2 -4
  2. package/.github/workflows/ci.yml +0 -72
  3. package/.smithery/shttp/module.js +0 -3
  4. package/.smithery/shttp/module.js.map +0 -7
  5. package/.smithery/stdio/index.cjs +0 -74
  6. package/.smithery/stdio/index.cjs.map +0 -7
  7. package/CHANGELOG.md +0 -65
  8. package/CODE_OF_CONDUCT.md +0 -34
  9. package/COMPARISON.md +0 -20
  10. package/CONTRIBUTING.md +0 -137
  11. package/DEVELOPMENT.md +0 -109
  12. package/LICENSE +0 -21
  13. package/README.md +0 -319
  14. package/ROADMAP.md +0 -24
  15. package/SECURITY.md +0 -88
  16. package/docs/COMMUNITY_FAQ.md +0 -48
  17. package/docs/COMPETITIVE_ANALYSIS.md +0 -90
  18. package/docs/DEMO_SCRIPT.md +0 -86
  19. package/docs/ENTERPRISE.md +0 -169
  20. package/docs/FAQ.md +0 -228
  21. package/docs/QUICK_START.md +0 -155
  22. package/docs/README.md +0 -67
  23. package/docs/RECURSIVE_SNAP_DEMO.gif +0 -0
  24. package/docs/social-preview-hq.png +0 -0
  25. package/docs/social-preview.png +0 -0
  26. package/examples/basic_usage.py +0 -84
  27. package/package.json.real +0 -24
  28. package/pyproject.toml +0 -50
  29. package/registry-server.json +0 -20
  30. package/scripts/demo_governance.py +0 -109
  31. package/scripts/sse_bridge.py +0 -87
  32. package/scripts/verify_windows_paths.py +0 -48
  33. package/server.json +0 -20
  34. package/src/mcp_server_nucleus/__init__.py +0 -8583
  35. package/src/mcp_server_nucleus/__main__.py +0 -9
  36. package/src/mcp_server_nucleus/cli.py +0 -1225
  37. package/src/mcp_server_nucleus/commitment_core.py +0 -146
  38. package/src/mcp_server_nucleus/commitment_ledger.py +0 -841
  39. package/src/mcp_server_nucleus/core/__init__.py +0 -6
  40. package/src/mcp_server_nucleus/core/orchestrator.py +0 -9
  41. package/src/mcp_server_nucleus/core/tool_registration_impl.py +0 -99
  42. package/src/mcp_server_nucleus/daemon/safety/lock.py +0 -121
  43. package/src/mcp_server_nucleus/deployment/render_integration.py +0 -4
  44. package/src/mcp_server_nucleus/hypervisor/__init__.py +0 -0
  45. package/src/mcp_server_nucleus/hypervisor/injector.py +0 -83
  46. package/src/mcp_server_nucleus/hypervisor/locker.py +0 -130
  47. package/src/mcp_server_nucleus/hypervisor/watchdog.py +0 -71
  48. package/src/mcp_server_nucleus/runtime/__init__.py +0 -58
  49. package/src/mcp_server_nucleus/runtime/agent.py +0 -517
  50. package/src/mcp_server_nucleus/runtime/agent_pool.py +0 -797
  51. package/src/mcp_server_nucleus/runtime/agents/base.py +0 -34
  52. package/src/mcp_server_nucleus/runtime/agents/oracle/manifest.json +0 -28
  53. package/src/mcp_server_nucleus/runtime/auth.py +0 -98
  54. package/src/mcp_server_nucleus/runtime/autopilot.py +0 -1057
  55. package/src/mcp_server_nucleus/runtime/broker.py +0 -126
  56. package/src/mcp_server_nucleus/runtime/budget.py +0 -153
  57. package/src/mcp_server_nucleus/runtime/capabilities/base.py +0 -20
  58. package/src/mcp_server_nucleus/runtime/capabilities/brain_ops.py +0 -253
  59. package/src/mcp_server_nucleus/runtime/capabilities/code_ops.py +0 -192
  60. package/src/mcp_server_nucleus/runtime/capabilities/depth_tracker.py +0 -81
  61. package/src/mcp_server_nucleus/runtime/capabilities/feature_map.py +0 -274
  62. package/src/mcp_server_nucleus/runtime/capabilities/marketing_engine.py +0 -205
  63. package/src/mcp_server_nucleus/runtime/capabilities/memory_ops.py +0 -79
  64. package/src/mcp_server_nucleus/runtime/capabilities/proof_system.py +0 -127
  65. package/src/mcp_server_nucleus/runtime/capabilities/render_ops.py +0 -80
  66. package/src/mcp_server_nucleus/runtime/capabilities/render_poller_cap.py +0 -266
  67. package/src/mcp_server_nucleus/runtime/capabilities/self_healing.py +0 -110
  68. package/src/mcp_server_nucleus/runtime/capabilities/strategy.py +0 -138
  69. package/src/mcp_server_nucleus/runtime/capabilities/synthesizer.py +0 -134
  70. package/src/mcp_server_nucleus/runtime/capabilities/web_ops.py +0 -94
  71. package/src/mcp_server_nucleus/runtime/common.py +0 -134
  72. package/src/mcp_server_nucleus/runtime/context_manager.py +0 -342
  73. package/src/mcp_server_nucleus/runtime/context_rules.json +0 -86
  74. package/src/mcp_server_nucleus/runtime/crdt_task_store.py +0 -349
  75. package/src/mcp_server_nucleus/runtime/critic.py +0 -150
  76. package/src/mcp_server_nucleus/runtime/daemon.py +0 -142
  77. package/src/mcp_server_nucleus/runtime/dashboard.py +0 -1087
  78. package/src/mcp_server_nucleus/runtime/depth_ops.py +0 -339
  79. package/src/mcp_server_nucleus/runtime/event_ops.py +0 -103
  80. package/src/mcp_server_nucleus/runtime/event_stream.py +0 -213
  81. package/src/mcp_server_nucleus/runtime/export.py +0 -64
  82. package/src/mcp_server_nucleus/runtime/factory.py +0 -594
  83. package/src/mcp_server_nucleus/runtime/federation.py +0 -1040
  84. package/src/mcp_server_nucleus/runtime/fetcher.py +0 -92
  85. package/src/mcp_server_nucleus/runtime/file_monitor.py +0 -208
  86. package/src/mcp_server_nucleus/runtime/firestore_bridge.py +0 -91
  87. package/src/mcp_server_nucleus/runtime/gcloud_ops.py +0 -186
  88. package/src/mcp_server_nucleus/runtime/hooks.py +0 -246
  89. package/src/mcp_server_nucleus/runtime/identity/gatekeeper.py +0 -106
  90. package/src/mcp_server_nucleus/runtime/identity/keygen.py +0 -147
  91. package/src/mcp_server_nucleus/runtime/identity/manifest.py +0 -62
  92. package/src/mcp_server_nucleus/runtime/identity/trust.py +0 -27
  93. package/src/mcp_server_nucleus/runtime/inspector.py +0 -74
  94. package/src/mcp_server_nucleus/runtime/installer.py +0 -81
  95. package/src/mcp_server_nucleus/runtime/ipc_auth.py +0 -377
  96. package/src/mcp_server_nucleus/runtime/lifecycle.py +0 -129
  97. package/src/mcp_server_nucleus/runtime/llm_client.py +0 -408
  98. package/src/mcp_server_nucleus/runtime/llm_tiers.json +0 -88
  99. package/src/mcp_server_nucleus/runtime/locking.py +0 -228
  100. package/src/mcp_server_nucleus/runtime/loops/fixer.py +0 -110
  101. package/src/mcp_server_nucleus/runtime/memory.py +0 -158
  102. package/src/mcp_server_nucleus/runtime/mounter.py +0 -210
  103. package/src/mcp_server_nucleus/runtime/mounter_ops.py +0 -250
  104. package/src/mcp_server_nucleus/runtime/nuke_protocol.py +0 -147
  105. package/src/mcp_server_nucleus/runtime/orchestrator.py +0 -370
  106. package/src/mcp_server_nucleus/runtime/orchestrator_unified.py +0 -263
  107. package/src/mcp_server_nucleus/runtime/orchestrator_v3.py +0 -617
  108. package/src/mcp_server_nucleus/runtime/plugin_loader.py +0 -84
  109. package/src/mcp_server_nucleus/runtime/policy.py +0 -117
  110. package/src/mcp_server_nucleus/runtime/profiling.py +0 -219
  111. package/src/mcp_server_nucleus/runtime/prometheus.py +0 -286
  112. package/src/mcp_server_nucleus/runtime/proposals.py +0 -101
  113. package/src/mcp_server_nucleus/runtime/publisher.py +0 -109
  114. package/src/mcp_server_nucleus/runtime/pulse.py +0 -516
  115. package/src/mcp_server_nucleus/runtime/registry.py +0 -82
  116. package/src/mcp_server_nucleus/runtime/render_ops.py +0 -83
  117. package/src/mcp_server_nucleus/runtime/schema_gen.py +0 -140
  118. package/src/mcp_server_nucleus/runtime/session_ops.py +0 -224
  119. package/src/mcp_server_nucleus/runtime/stdio_server.py +0 -633
  120. package/src/mcp_server_nucleus/runtime/storage.py +0 -83
  121. package/src/mcp_server_nucleus/runtime/strategy.py +0 -91
  122. package/src/mcp_server_nucleus/runtime/swarm.py +0 -170
  123. package/src/mcp_server_nucleus/runtime/sync_ops.py +0 -878
  124. package/src/mcp_server_nucleus/runtime/task_ingestion.py +0 -1020
  125. package/src/mcp_server_nucleus/runtime/task_ops.py +0 -449
  126. package/src/mcp_server_nucleus/runtime/task_scheduler.py +0 -488
  127. package/src/mcp_server_nucleus/runtime/team.py +0 -59
  128. package/src/mcp_server_nucleus/runtime/triggers.py +0 -237
  129. package/src/mcp_server_nucleus/runtime/vector_store.py +0 -125
  130. package/src/mcp_server_nucleus/runtime/watcher.py +0 -112
  131. package/src/mcp_server_nucleus/tool_tiers.py +0 -243
  132. package/tests/__init__.py +0 -1
  133. package/tests/conftest.py +0 -42
  134. package/tests/test_core.py +0 -235
  135. 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
@@ -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"])
@@ -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