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.
Files changed (34) hide show
  1. rakam_systems_core/__init__.py +41 -0
  2. rakam_systems_core/ai_core/__init__.py +68 -0
  3. rakam_systems_core/ai_core/base.py +142 -0
  4. rakam_systems_core/ai_core/config.py +12 -0
  5. rakam_systems_core/ai_core/config_loader.py +580 -0
  6. rakam_systems_core/ai_core/config_schema.py +395 -0
  7. rakam_systems_core/ai_core/interfaces/__init__.py +30 -0
  8. rakam_systems_core/ai_core/interfaces/agent.py +83 -0
  9. rakam_systems_core/ai_core/interfaces/chat_history.py +122 -0
  10. rakam_systems_core/ai_core/interfaces/chunker.py +11 -0
  11. rakam_systems_core/ai_core/interfaces/embedding_model.py +10 -0
  12. rakam_systems_core/ai_core/interfaces/indexer.py +10 -0
  13. rakam_systems_core/ai_core/interfaces/llm_gateway.py +139 -0
  14. rakam_systems_core/ai_core/interfaces/loader.py +86 -0
  15. rakam_systems_core/ai_core/interfaces/reranker.py +10 -0
  16. rakam_systems_core/ai_core/interfaces/retriever.py +11 -0
  17. rakam_systems_core/ai_core/interfaces/tool.py +162 -0
  18. rakam_systems_core/ai_core/interfaces/tool_invoker.py +260 -0
  19. rakam_systems_core/ai_core/interfaces/tool_loader.py +374 -0
  20. rakam_systems_core/ai_core/interfaces/tool_registry.py +287 -0
  21. rakam_systems_core/ai_core/interfaces/vectorstore.py +37 -0
  22. rakam_systems_core/ai_core/mcp/README.md +545 -0
  23. rakam_systems_core/ai_core/mcp/__init__.py +0 -0
  24. rakam_systems_core/ai_core/mcp/mcp_server.py +334 -0
  25. rakam_systems_core/ai_core/tracking.py +602 -0
  26. rakam_systems_core/ai_core/vs_core.py +55 -0
  27. rakam_systems_core/ai_utils/__init__.py +16 -0
  28. rakam_systems_core/ai_utils/logging.py +126 -0
  29. rakam_systems_core/ai_utils/metrics.py +10 -0
  30. rakam_systems_core/ai_utils/s3.py +480 -0
  31. rakam_systems_core/ai_utils/tracing.py +5 -0
  32. rakam_systems_core-0.1.1rc7.dist-info/METADATA +162 -0
  33. rakam_systems_core-0.1.1rc7.dist-info/RECORD +34 -0
  34. 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