rakam-systems-core 0.1.1rc7__py3-none-any.whl
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.
- rakam_systems_core/__init__.py +41 -0
- rakam_systems_core/ai_core/__init__.py +68 -0
- rakam_systems_core/ai_core/base.py +142 -0
- rakam_systems_core/ai_core/config.py +12 -0
- rakam_systems_core/ai_core/config_loader.py +580 -0
- rakam_systems_core/ai_core/config_schema.py +395 -0
- rakam_systems_core/ai_core/interfaces/__init__.py +30 -0
- rakam_systems_core/ai_core/interfaces/agent.py +83 -0
- rakam_systems_core/ai_core/interfaces/chat_history.py +122 -0
- rakam_systems_core/ai_core/interfaces/chunker.py +11 -0
- rakam_systems_core/ai_core/interfaces/embedding_model.py +10 -0
- rakam_systems_core/ai_core/interfaces/indexer.py +10 -0
- rakam_systems_core/ai_core/interfaces/llm_gateway.py +139 -0
- rakam_systems_core/ai_core/interfaces/loader.py +86 -0
- rakam_systems_core/ai_core/interfaces/reranker.py +10 -0
- rakam_systems_core/ai_core/interfaces/retriever.py +11 -0
- rakam_systems_core/ai_core/interfaces/tool.py +162 -0
- rakam_systems_core/ai_core/interfaces/tool_invoker.py +260 -0
- rakam_systems_core/ai_core/interfaces/tool_loader.py +374 -0
- rakam_systems_core/ai_core/interfaces/tool_registry.py +287 -0
- rakam_systems_core/ai_core/interfaces/vectorstore.py +37 -0
- rakam_systems_core/ai_core/mcp/README.md +545 -0
- rakam_systems_core/ai_core/mcp/__init__.py +0 -0
- rakam_systems_core/ai_core/mcp/mcp_server.py +334 -0
- rakam_systems_core/ai_core/tracking.py +602 -0
- rakam_systems_core/ai_core/vs_core.py +55 -0
- rakam_systems_core/ai_utils/__init__.py +16 -0
- rakam_systems_core/ai_utils/logging.py +126 -0
- rakam_systems_core/ai_utils/metrics.py +10 -0
- rakam_systems_core/ai_utils/s3.py +480 -0
- rakam_systems_core/ai_utils/tracing.py +5 -0
- rakam_systems_core-0.1.1rc7.dist-info/METADATA +162 -0
- rakam_systems_core-0.1.1rc7.dist-info/RECORD +34 -0
- rakam_systems_core-0.1.1rc7.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
# MCP Server Module
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The `mcp_server` module provides a Model Context Protocol (MCP) server implementation for message-based component communication. It acts as a lightweight message router that enables loose coupling between components.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
✅ **Component Registration** - Register and manage multiple components
|
|
10
|
+
✅ **Message Routing** - Route messages between components using sender/receiver pattern
|
|
11
|
+
✅ **Async Support** - Full support for both synchronous and asynchronous operations
|
|
12
|
+
✅ **Flexible Handlers** - Components can implement custom message handlers
|
|
13
|
+
✅ **Auto Argument Extraction** - Automatically extracts and passes arguments from messages
|
|
14
|
+
✅ **Error Handling** - Comprehensive error handling with logging
|
|
15
|
+
✅ **Component Discovery** - Query and list registered components
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Basic Usage
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from rakam_systems_core.ai_core.mcp.mcp_server import MCPServer
|
|
23
|
+
from rakam_systems_core.ai_core.base import BaseComponent
|
|
24
|
+
|
|
25
|
+
# Create server
|
|
26
|
+
server = MCPServer(name="my_server")
|
|
27
|
+
server.setup()
|
|
28
|
+
|
|
29
|
+
# Create a component
|
|
30
|
+
class MyTool(BaseComponent):
|
|
31
|
+
def run(self, value: int):
|
|
32
|
+
return {'result': value * 2}
|
|
33
|
+
|
|
34
|
+
# Register component
|
|
35
|
+
tool = MyTool(name="calculator")
|
|
36
|
+
server.register_component(tool)
|
|
37
|
+
|
|
38
|
+
# Send message
|
|
39
|
+
result = server.send_message(
|
|
40
|
+
sender="client",
|
|
41
|
+
receiver="calculator",
|
|
42
|
+
message={'arguments': {'value': 5}}
|
|
43
|
+
)
|
|
44
|
+
# result = {'result': 10}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Async Usage
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import asyncio
|
|
51
|
+
|
|
52
|
+
# Async component
|
|
53
|
+
class AsyncTool(BaseComponent):
|
|
54
|
+
async def run(self, query: str):
|
|
55
|
+
await asyncio.sleep(0.1) # Simulate async work
|
|
56
|
+
return {'query': query, 'results': [...]}
|
|
57
|
+
|
|
58
|
+
# Register
|
|
59
|
+
tool = AsyncTool(name="search")
|
|
60
|
+
server.register_component(tool)
|
|
61
|
+
|
|
62
|
+
# Send async message
|
|
63
|
+
result = await server.asend_message(
|
|
64
|
+
sender="client",
|
|
65
|
+
receiver="search",
|
|
66
|
+
message={'arguments': {'query': 'test'}}
|
|
67
|
+
)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## API Reference
|
|
71
|
+
|
|
72
|
+
### MCPServer
|
|
73
|
+
|
|
74
|
+
#### Constructor
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
MCPServer(
|
|
78
|
+
name: str = "mcp_server",
|
|
79
|
+
config: Optional[Dict[str, Any]] = None,
|
|
80
|
+
enable_logging: bool = True
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Parameters:**
|
|
85
|
+
|
|
86
|
+
- `name` (str): Name of the MCP server
|
|
87
|
+
- `config` (Dict, optional): Configuration dictionary
|
|
88
|
+
- `enable_logging` (bool): Whether to enable detailed logging
|
|
89
|
+
|
|
90
|
+
**Example:**
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
server = MCPServer(
|
|
94
|
+
name="production_server",
|
|
95
|
+
enable_logging=True
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Methods
|
|
100
|
+
|
|
101
|
+
##### `register_component(component: BaseComponent) -> None`
|
|
102
|
+
|
|
103
|
+
Register a component with the server.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
server.register_component(my_component)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
##### `unregister_component(component_name: str) -> bool`
|
|
110
|
+
|
|
111
|
+
Unregister a component.
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
success = server.unregister_component("my_component")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
##### `send_message(sender: str, receiver: str, message: Dict[str, Any]) -> Any`
|
|
118
|
+
|
|
119
|
+
Send a synchronous message to a component.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
result = server.send_message(
|
|
123
|
+
sender="client",
|
|
124
|
+
receiver="tool_name",
|
|
125
|
+
message={
|
|
126
|
+
'action': 'invoke_tool',
|
|
127
|
+
'arguments': {'param': 'value'}
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
##### `async asend_message(sender: str, receiver: str, message: Dict[str, Any]) -> Any`
|
|
133
|
+
|
|
134
|
+
Send an asynchronous message to a component.
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
result = await server.asend_message(
|
|
138
|
+
sender="client",
|
|
139
|
+
receiver="tool_name",
|
|
140
|
+
message={
|
|
141
|
+
'action': 'invoke_tool',
|
|
142
|
+
'arguments': {'param': 'value'}
|
|
143
|
+
}
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
##### `get_component(component_name: str) -> Optional[BaseComponent]`
|
|
148
|
+
|
|
149
|
+
Get a registered component by name.
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
component = server.get_component("tool_name")
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
##### `list_components() -> List[str]`
|
|
156
|
+
|
|
157
|
+
List all registered component names (sorted).
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
names = server.list_components()
|
|
161
|
+
# ['component1', 'component2', ...]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
##### `has_component(component_name: str) -> bool`
|
|
165
|
+
|
|
166
|
+
Check if a component is registered.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
if server.has_component("tool_name"):
|
|
170
|
+
# Component is registered
|
|
171
|
+
pass
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
##### `get_stats() -> Dict[str, Any]`
|
|
175
|
+
|
|
176
|
+
Get server statistics.
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
stats = server.get_stats()
|
|
180
|
+
# {
|
|
181
|
+
# 'name': 'my_server',
|
|
182
|
+
# 'component_count': 5,
|
|
183
|
+
# 'components': ['comp1', 'comp2', ...],
|
|
184
|
+
# 'logging_enabled': True
|
|
185
|
+
# }
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Message Format
|
|
189
|
+
|
|
190
|
+
Messages should follow this structure:
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
message = {
|
|
194
|
+
'action': 'invoke_tool', # Optional, describes the action
|
|
195
|
+
'tool_name': 'my_tool', # Optional, tool identifier
|
|
196
|
+
'arguments': { # Required for components without custom handlers
|
|
197
|
+
'param1': 'value1',
|
|
198
|
+
'param2': 'value2'
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The server automatically extracts `arguments` and passes them to the component's `run()` method.
|
|
204
|
+
|
|
205
|
+
## Component Implementation
|
|
206
|
+
|
|
207
|
+
### Basic Component
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from rakam_systems_core.ai_core.base import BaseComponent
|
|
211
|
+
|
|
212
|
+
class MyComponent(BaseComponent):
|
|
213
|
+
"""Component with automatic argument extraction."""
|
|
214
|
+
|
|
215
|
+
def run(self, param1: str, param2: int = 0):
|
|
216
|
+
# Arguments are automatically extracted from message
|
|
217
|
+
return {
|
|
218
|
+
'param1': param1,
|
|
219
|
+
'param2': param2,
|
|
220
|
+
'processed': True
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Component with Custom Handler
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
class CustomHandlerComponent(BaseComponent):
|
|
228
|
+
"""Component with custom message handling."""
|
|
229
|
+
|
|
230
|
+
def handle_message(self, sender: str, message: Dict[str, Any]):
|
|
231
|
+
# Custom logic for handling messages
|
|
232
|
+
action = message.get('action')
|
|
233
|
+
|
|
234
|
+
if action == 'special_action':
|
|
235
|
+
return self._handle_special(message)
|
|
236
|
+
else:
|
|
237
|
+
# Fall back to default behavior
|
|
238
|
+
return self.run(**message.get('arguments', {}))
|
|
239
|
+
|
|
240
|
+
def _handle_special(self, message):
|
|
241
|
+
return {'status': 'special_handled'}
|
|
242
|
+
|
|
243
|
+
def run(self, **kwargs):
|
|
244
|
+
return {'status': 'normal'}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Async Component
|
|
248
|
+
|
|
249
|
+
```python
|
|
250
|
+
class AsyncComponent(BaseComponent):
|
|
251
|
+
"""Async component."""
|
|
252
|
+
|
|
253
|
+
async def run(self, query: str):
|
|
254
|
+
# Perform async operations
|
|
255
|
+
results = await self._async_operation(query)
|
|
256
|
+
return {'results': results}
|
|
257
|
+
|
|
258
|
+
async def _async_operation(self, query):
|
|
259
|
+
await asyncio.sleep(0.1)
|
|
260
|
+
return [query, query.upper()]
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Async Custom Handler
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
class AsyncHandlerComponent(BaseComponent):
|
|
267
|
+
"""Async component with custom handler."""
|
|
268
|
+
|
|
269
|
+
async def handle_message(self, sender: str, message: Dict[str, Any]):
|
|
270
|
+
# Async custom handling
|
|
271
|
+
await asyncio.sleep(0.01)
|
|
272
|
+
return {
|
|
273
|
+
'sender': sender,
|
|
274
|
+
'handled': True,
|
|
275
|
+
'async': True
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
async def run(self, **kwargs):
|
|
279
|
+
return {'handled': False}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Usage Patterns
|
|
283
|
+
|
|
284
|
+
### Pattern 1: Simple Tool Registry
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
# Server as a tool registry
|
|
288
|
+
server = MCPServer(name="tool_registry")
|
|
289
|
+
server.setup()
|
|
290
|
+
|
|
291
|
+
# Register tools
|
|
292
|
+
server.register_component(SearchTool(name="search"))
|
|
293
|
+
server.register_component(CalculatorTool(name="calc"))
|
|
294
|
+
server.register_component(DatabaseTool(name="db"))
|
|
295
|
+
|
|
296
|
+
# List available tools
|
|
297
|
+
available = server.list_components()
|
|
298
|
+
print(f"Available tools: {available}")
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Pattern 2: Request-Response Pattern
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
# Client sends request
|
|
305
|
+
response = server.send_message(
|
|
306
|
+
sender="user_client",
|
|
307
|
+
receiver="search",
|
|
308
|
+
message={
|
|
309
|
+
'action': 'search',
|
|
310
|
+
'arguments': {
|
|
311
|
+
'query': 'machine learning',
|
|
312
|
+
'top_k': 5
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
# Process response
|
|
318
|
+
for result in response['results']:
|
|
319
|
+
print(result)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Pattern 3: Async Concurrent Operations
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
# Execute multiple operations concurrently
|
|
326
|
+
results = await asyncio.gather(
|
|
327
|
+
server.asend_message(
|
|
328
|
+
sender="client",
|
|
329
|
+
receiver="search",
|
|
330
|
+
message={'arguments': {'query': 'AI'}}
|
|
331
|
+
),
|
|
332
|
+
server.asend_message(
|
|
333
|
+
sender="client",
|
|
334
|
+
receiver="database",
|
|
335
|
+
message={'arguments': {'table': 'users'}}
|
|
336
|
+
),
|
|
337
|
+
server.asend_message(
|
|
338
|
+
sender="client",
|
|
339
|
+
receiver="calculator",
|
|
340
|
+
message={'arguments': {'value': 42}}
|
|
341
|
+
)
|
|
342
|
+
)
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Pattern 4: Tool Invoker Integration
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
from rakam_systems_core.ai_core.interfaces import ToolRegistry, ToolInvoker
|
|
349
|
+
|
|
350
|
+
# Create MCP server
|
|
351
|
+
server = MCPServer(name="tool_server")
|
|
352
|
+
server.setup()
|
|
353
|
+
|
|
354
|
+
# Register components
|
|
355
|
+
server.register_component(SearchTool(name="search"))
|
|
356
|
+
|
|
357
|
+
# Register in tool registry
|
|
358
|
+
registry = ToolRegistry()
|
|
359
|
+
registry.register_mcp_tool(
|
|
360
|
+
name="mcp_search",
|
|
361
|
+
mcp_server="tool_server",
|
|
362
|
+
mcp_tool_name="search",
|
|
363
|
+
description="Search documents"
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
# Create invoker
|
|
367
|
+
invoker = ToolInvoker(registry)
|
|
368
|
+
invoker.register_mcp_server("tool_server", server)
|
|
369
|
+
|
|
370
|
+
# Invoke via tool system
|
|
371
|
+
result = await invoker.ainvoke(
|
|
372
|
+
"mcp_search",
|
|
373
|
+
query="test",
|
|
374
|
+
top_k=5
|
|
375
|
+
)
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Error Handling
|
|
379
|
+
|
|
380
|
+
The server provides comprehensive error handling:
|
|
381
|
+
|
|
382
|
+
### Component Not Found
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
try:
|
|
386
|
+
result = server.send_message(
|
|
387
|
+
sender="client",
|
|
388
|
+
receiver="nonexistent",
|
|
389
|
+
message={'arguments': {}}
|
|
390
|
+
)
|
|
391
|
+
except KeyError as e:
|
|
392
|
+
print(f"Component not found: {e}")
|
|
393
|
+
# Lists available components in error message
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Component Errors
|
|
397
|
+
|
|
398
|
+
```python
|
|
399
|
+
# Errors in components are propagated
|
|
400
|
+
class ErrorComponent(BaseComponent):
|
|
401
|
+
def run(self):
|
|
402
|
+
raise ValueError("Something went wrong")
|
|
403
|
+
|
|
404
|
+
server.register_component(ErrorComponent(name="error"))
|
|
405
|
+
|
|
406
|
+
try:
|
|
407
|
+
server.send_message(
|
|
408
|
+
sender="client",
|
|
409
|
+
receiver="error",
|
|
410
|
+
message={'arguments': {}}
|
|
411
|
+
)
|
|
412
|
+
except ValueError as e:
|
|
413
|
+
print(f"Component error: {e}")
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## Best Practices
|
|
417
|
+
|
|
418
|
+
### 1. Descriptive Names
|
|
419
|
+
|
|
420
|
+
```python
|
|
421
|
+
# Good
|
|
422
|
+
server = MCPServer(name="production_vector_store_server")
|
|
423
|
+
|
|
424
|
+
# Avoid
|
|
425
|
+
server = MCPServer(name="server1")
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### 2. Consistent Message Format
|
|
429
|
+
|
|
430
|
+
```python
|
|
431
|
+
# Consistent structure
|
|
432
|
+
message = {
|
|
433
|
+
'action': 'invoke_tool',
|
|
434
|
+
'arguments': {
|
|
435
|
+
'param1': 'value1',
|
|
436
|
+
'param2': 'value2'
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### 3. Error Handling
|
|
442
|
+
|
|
443
|
+
```python
|
|
444
|
+
async def safe_message_send(server, receiver, message):
|
|
445
|
+
"""Wrapper with error handling."""
|
|
446
|
+
try:
|
|
447
|
+
return await server.asend_message(
|
|
448
|
+
sender="client",
|
|
449
|
+
receiver=receiver,
|
|
450
|
+
message=message
|
|
451
|
+
)
|
|
452
|
+
except KeyError:
|
|
453
|
+
print(f"Component '{receiver}' not found")
|
|
454
|
+
return None
|
|
455
|
+
except Exception as e:
|
|
456
|
+
print(f"Error: {e}")
|
|
457
|
+
return None
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### 4. Component Validation
|
|
461
|
+
|
|
462
|
+
```python
|
|
463
|
+
# Check before sending
|
|
464
|
+
if server.has_component("search"):
|
|
465
|
+
result = server.send_message(...)
|
|
466
|
+
else:
|
|
467
|
+
print("Search component not available")
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### 5. Resource Management
|
|
471
|
+
|
|
472
|
+
```python
|
|
473
|
+
# Unregister when done
|
|
474
|
+
try:
|
|
475
|
+
# Use component
|
|
476
|
+
result = server.send_message(...)
|
|
477
|
+
finally:
|
|
478
|
+
# Clean up
|
|
479
|
+
server.unregister_component("temp_component")
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Testing
|
|
483
|
+
|
|
484
|
+
The module includes comprehensive tests. Run them with:
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
pytest app/rakam_systems/tests/test_mcp_server.py -v
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Tests cover:
|
|
491
|
+
|
|
492
|
+
- Component registration/unregistration
|
|
493
|
+
- Synchronous message routing
|
|
494
|
+
- Asynchronous message routing
|
|
495
|
+
- Error handling
|
|
496
|
+
- Component discovery
|
|
497
|
+
- Custom handlers
|
|
498
|
+
- Mixed async/sync operations
|
|
499
|
+
|
|
500
|
+
## Advanced Features
|
|
501
|
+
|
|
502
|
+
### Logging Control
|
|
503
|
+
|
|
504
|
+
```python
|
|
505
|
+
# Enable detailed logging
|
|
506
|
+
server = MCPServer(name="debug_server", enable_logging=True)
|
|
507
|
+
|
|
508
|
+
# Disable logging for production
|
|
509
|
+
server = MCPServer(name="prod_server", enable_logging=False)
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Statistics Monitoring
|
|
513
|
+
|
|
514
|
+
```python
|
|
515
|
+
# Get server stats
|
|
516
|
+
stats = server.get_stats()
|
|
517
|
+
|
|
518
|
+
print(f"Server: {stats['name']}")
|
|
519
|
+
print(f"Components: {stats['component_count']}")
|
|
520
|
+
print(f"Component list: {stats['components']}")
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Dynamic Component Management
|
|
524
|
+
|
|
525
|
+
```python
|
|
526
|
+
# Hot-swap components
|
|
527
|
+
server.unregister_component("old_version")
|
|
528
|
+
server.register_component(NewVersion(name="service"))
|
|
529
|
+
|
|
530
|
+
# Conditional registration
|
|
531
|
+
if os.getenv("ENABLE_FEATURE_X"):
|
|
532
|
+
server.register_component(FeatureX(name="feature_x"))
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## See Also
|
|
536
|
+
|
|
537
|
+
- **Tool System**: `app/rakam_systems/rakam_systems/ai_core/interfaces/tool_registry.py`
|
|
538
|
+
- **Tool Invoker**: `app/rakam_systems/rakam_systems/ai_core/interfaces/tool_invoker.py`
|
|
539
|
+
- **Base Component**: `app/rakam_systems/rakam_systems/ai_core/base.py`
|
|
540
|
+
- **Examples**: `app/rakam_systems/rakam_systems/examples/ai_agents_examples/tool_system_example.py`
|
|
541
|
+
- **MCP Guide**: `docs/MCP_VECTOR_STORE_GUIDE.md`
|
|
542
|
+
|
|
543
|
+
## License
|
|
544
|
+
|
|
545
|
+
Part of the rakam_systems framework.
|
|
File without changes
|