kailash 0.1.4__py3-none-any.whl → 0.2.0__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 (83) hide show
  1. kailash/__init__.py +1 -1
  2. kailash/access_control.py +740 -0
  3. kailash/api/__main__.py +6 -0
  4. kailash/api/auth.py +668 -0
  5. kailash/api/custom_nodes.py +285 -0
  6. kailash/api/custom_nodes_secure.py +377 -0
  7. kailash/api/database.py +620 -0
  8. kailash/api/studio.py +915 -0
  9. kailash/api/studio_secure.py +893 -0
  10. kailash/mcp/__init__.py +53 -0
  11. kailash/mcp/__main__.py +13 -0
  12. kailash/mcp/ai_registry_server.py +712 -0
  13. kailash/mcp/client.py +447 -0
  14. kailash/mcp/client_new.py +334 -0
  15. kailash/mcp/server.py +293 -0
  16. kailash/mcp/server_new.py +336 -0
  17. kailash/mcp/servers/__init__.py +12 -0
  18. kailash/mcp/servers/ai_registry.py +289 -0
  19. kailash/nodes/__init__.py +4 -2
  20. kailash/nodes/ai/__init__.py +38 -0
  21. kailash/nodes/ai/a2a.py +1790 -0
  22. kailash/nodes/ai/agents.py +116 -2
  23. kailash/nodes/ai/ai_providers.py +206 -8
  24. kailash/nodes/ai/intelligent_agent_orchestrator.py +2108 -0
  25. kailash/nodes/ai/iterative_llm_agent.py +1280 -0
  26. kailash/nodes/ai/llm_agent.py +324 -1
  27. kailash/nodes/ai/self_organizing.py +1623 -0
  28. kailash/nodes/api/http.py +106 -25
  29. kailash/nodes/api/rest.py +116 -21
  30. kailash/nodes/base.py +15 -2
  31. kailash/nodes/base_async.py +45 -0
  32. kailash/nodes/base_cycle_aware.py +374 -0
  33. kailash/nodes/base_with_acl.py +338 -0
  34. kailash/nodes/code/python.py +135 -27
  35. kailash/nodes/data/readers.py +116 -53
  36. kailash/nodes/data/writers.py +16 -6
  37. kailash/nodes/logic/__init__.py +8 -0
  38. kailash/nodes/logic/async_operations.py +48 -9
  39. kailash/nodes/logic/convergence.py +642 -0
  40. kailash/nodes/logic/loop.py +153 -0
  41. kailash/nodes/logic/operations.py +212 -27
  42. kailash/nodes/logic/workflow.py +26 -18
  43. kailash/nodes/mixins/__init__.py +11 -0
  44. kailash/nodes/mixins/mcp.py +228 -0
  45. kailash/nodes/mixins.py +387 -0
  46. kailash/nodes/transform/__init__.py +8 -1
  47. kailash/nodes/transform/processors.py +119 -4
  48. kailash/runtime/__init__.py +2 -1
  49. kailash/runtime/access_controlled.py +458 -0
  50. kailash/runtime/local.py +106 -33
  51. kailash/runtime/parallel_cyclic.py +529 -0
  52. kailash/sdk_exceptions.py +90 -5
  53. kailash/security.py +845 -0
  54. kailash/tracking/manager.py +38 -15
  55. kailash/tracking/models.py +1 -1
  56. kailash/tracking/storage/filesystem.py +30 -2
  57. kailash/utils/__init__.py +8 -0
  58. kailash/workflow/__init__.py +18 -0
  59. kailash/workflow/convergence.py +270 -0
  60. kailash/workflow/cycle_analyzer.py +768 -0
  61. kailash/workflow/cycle_builder.py +573 -0
  62. kailash/workflow/cycle_config.py +709 -0
  63. kailash/workflow/cycle_debugger.py +760 -0
  64. kailash/workflow/cycle_exceptions.py +601 -0
  65. kailash/workflow/cycle_profiler.py +671 -0
  66. kailash/workflow/cycle_state.py +338 -0
  67. kailash/workflow/cyclic_runner.py +985 -0
  68. kailash/workflow/graph.py +500 -39
  69. kailash/workflow/migration.py +768 -0
  70. kailash/workflow/safety.py +365 -0
  71. kailash/workflow/templates.py +744 -0
  72. kailash/workflow/validation.py +693 -0
  73. {kailash-0.1.4.dist-info → kailash-0.2.0.dist-info}/METADATA +446 -13
  74. kailash-0.2.0.dist-info/RECORD +125 -0
  75. kailash/nodes/mcp/__init__.py +0 -11
  76. kailash/nodes/mcp/client.py +0 -554
  77. kailash/nodes/mcp/resource.py +0 -682
  78. kailash/nodes/mcp/server.py +0 -577
  79. kailash-0.1.4.dist-info/RECORD +0 -85
  80. {kailash-0.1.4.dist-info → kailash-0.2.0.dist-info}/WHEEL +0 -0
  81. {kailash-0.1.4.dist-info → kailash-0.2.0.dist-info}/entry_points.txt +0 -0
  82. {kailash-0.1.4.dist-info → kailash-0.2.0.dist-info}/licenses/LICENSE +0 -0
  83. {kailash-0.1.4.dist-info → kailash-0.2.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,712 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ AI Registry MCP Server using Anthropic's Official MCP Python SDK.
4
+
5
+ This creates a real MCP server that exposes AI Registry tools following
6
+ the actual Model Context Protocol specification.
7
+
8
+ Run as: python -m kailash.mcp.ai_registry_server
9
+ """
10
+
11
+ import asyncio
12
+ import json
13
+ import os
14
+ from typing import Any, Dict, List, Optional
15
+
16
+ from mcp.server import Server
17
+ from mcp.types import Resource, TextContent, Tool
18
+
19
+
20
+ class AIRegistryServer:
21
+ """
22
+ AI Registry MCP Server providing real ISO/IEC AI use case data.
23
+
24
+ This server implements the actual MCP protocol using Anthropic's official SDK,
25
+ providing 8 real tools for AI use case discovery and analysis.
26
+ """
27
+
28
+ def __init__(self, registry_file: str = "research/combined_ai_registry.json"):
29
+ """Initialize the AI Registry MCP server."""
30
+ self.server = Server("ai-registry")
31
+ self.registry_data = self._load_registry_data(registry_file)
32
+ self._setup_tools()
33
+ self._setup_resources()
34
+
35
+ def _load_registry_data(self, registry_file: str) -> Dict[str, Any]:
36
+ """Load AI Registry data from JSON file."""
37
+ # Handle both absolute and relative paths
38
+ if not os.path.isabs(registry_file):
39
+ # Try relative to current working directory first
40
+ if os.path.exists(registry_file):
41
+ pass # Use as-is
42
+ else:
43
+ # Try relative to this module's directory
44
+ module_dir = os.path.dirname(os.path.abspath(__file__))
45
+ project_root = os.path.dirname(
46
+ os.path.dirname(os.path.dirname(module_dir))
47
+ )
48
+ registry_file = os.path.join(project_root, registry_file)
49
+
50
+ try:
51
+ with open(registry_file, "r", encoding="utf-8") as f:
52
+ return json.load(f)
53
+ except FileNotFoundError:
54
+ # Return mock data if file not found
55
+ return {
56
+ "registry_info": {
57
+ "source": "AI Registry MCP Server",
58
+ "total_cases": 3,
59
+ "domains": 2,
60
+ },
61
+ "use_cases": [
62
+ {
63
+ "use_case_id": 42,
64
+ "name": "Medical Diagnosis Assistant",
65
+ "application_domain": "Healthcare",
66
+ "description": "AI-powered diagnostic support system for medical professionals",
67
+ "ai_methods": [
68
+ "Machine Learning",
69
+ "Deep Learning",
70
+ "Natural Language Processing",
71
+ ],
72
+ "tasks": [
73
+ "Classification",
74
+ "Diagnosis Support",
75
+ "Risk Assessment",
76
+ ],
77
+ "status": "PoC",
78
+ "challenges": "Data privacy, model interpretability, regulatory compliance",
79
+ "kpis": [
80
+ "Diagnostic accuracy",
81
+ "Time to diagnosis",
82
+ "User satisfaction",
83
+ ],
84
+ },
85
+ {
86
+ "use_case_id": 87,
87
+ "name": "Clinical Decision Support",
88
+ "application_domain": "Healthcare",
89
+ "description": "Evidence-based recommendations for clinical decision making",
90
+ "ai_methods": ["Expert Systems", "Machine Learning"],
91
+ "tasks": ["Decision Support", "Risk Assessment"],
92
+ "status": "Production",
93
+ "challenges": "Integration with EHR systems, physician adoption",
94
+ "kpis": [
95
+ "Decision accuracy",
96
+ "Time savings",
97
+ "Physician satisfaction",
98
+ ],
99
+ },
100
+ {
101
+ "use_case_id": 156,
102
+ "name": "Manufacturing Quality Control",
103
+ "application_domain": "Manufacturing",
104
+ "description": "Automated quality inspection using computer vision",
105
+ "ai_methods": ["Computer Vision", "Deep Learning"],
106
+ "tasks": ["Detection", "Classification", "Quality Control"],
107
+ "status": "Production",
108
+ "challenges": "Real-time processing, accuracy requirements",
109
+ "kpis": [
110
+ "Detection accuracy",
111
+ "Processing speed",
112
+ "Cost savings",
113
+ ],
114
+ },
115
+ ],
116
+ }
117
+ except Exception as e:
118
+ raise ValueError(
119
+ f"Failed to load AI registry data from {registry_file}: {e}"
120
+ )
121
+
122
+ def _setup_tools(self):
123
+ """Setup MCP tools using the official SDK."""
124
+
125
+ @self.server.list_tools()
126
+ async def handle_list_tools():
127
+ """List all available AI Registry tools."""
128
+ return [
129
+ Tool(
130
+ name="search_use_cases",
131
+ description="Advanced search across AI use cases with domain and method filters",
132
+ inputSchema={
133
+ "type": "object",
134
+ "properties": {
135
+ "query": {"type": "string", "description": "Search query"},
136
+ "domains": {
137
+ "type": "array",
138
+ "items": {"type": "string"},
139
+ "description": "Filter by domains",
140
+ },
141
+ "methods": {
142
+ "type": "array",
143
+ "items": {"type": "string"},
144
+ "description": "Filter by AI methods",
145
+ },
146
+ "limit": {
147
+ "type": "integer",
148
+ "description": "Maximum results",
149
+ "default": 10,
150
+ },
151
+ },
152
+ "required": ["query"],
153
+ },
154
+ ),
155
+ Tool(
156
+ name="filter_by_domain",
157
+ description="Get all use cases in a specific application domain",
158
+ inputSchema={
159
+ "type": "object",
160
+ "properties": {
161
+ "domain": {
162
+ "type": "string",
163
+ "description": "Application domain",
164
+ },
165
+ "status": {
166
+ "type": "string",
167
+ "description": "Optional status filter",
168
+ },
169
+ "limit": {
170
+ "type": "integer",
171
+ "description": "Maximum results",
172
+ "default": 20,
173
+ },
174
+ },
175
+ "required": ["domain"],
176
+ },
177
+ ),
178
+ Tool(
179
+ name="get_use_case_details",
180
+ description="Get complete details for a specific use case by ID",
181
+ inputSchema={
182
+ "type": "object",
183
+ "properties": {
184
+ "use_case_id": {
185
+ "type": "integer",
186
+ "description": "Use case ID",
187
+ }
188
+ },
189
+ "required": ["use_case_id"],
190
+ },
191
+ ),
192
+ Tool(
193
+ name="analyze_domain_trends",
194
+ description="Analyze trends, methods, and patterns within a specific domain",
195
+ inputSchema={
196
+ "type": "object",
197
+ "properties": {
198
+ "domain": {
199
+ "type": "string",
200
+ "description": "Application domain to analyze",
201
+ },
202
+ "include_details": {
203
+ "type": "boolean",
204
+ "description": "Include detailed examples",
205
+ "default": False,
206
+ },
207
+ },
208
+ "required": ["domain"],
209
+ },
210
+ ),
211
+ Tool(
212
+ name="recommend_similar",
213
+ description="Find similar use cases based on various similarity factors",
214
+ inputSchema={
215
+ "type": "object",
216
+ "properties": {
217
+ "use_case_id": {
218
+ "type": "integer",
219
+ "description": "Reference use case ID",
220
+ },
221
+ "similarity_factors": {
222
+ "type": "array",
223
+ "items": {"type": "string"},
224
+ "description": "Factors to consider",
225
+ },
226
+ "limit": {
227
+ "type": "integer",
228
+ "description": "Maximum similar cases",
229
+ "default": 5,
230
+ },
231
+ },
232
+ "required": ["use_case_id"],
233
+ },
234
+ ),
235
+ Tool(
236
+ name="estimate_complexity",
237
+ description="Assess implementation complexity based on methods, challenges, and KPIs",
238
+ inputSchema={
239
+ "type": "object",
240
+ "properties": {
241
+ "use_case_id": {
242
+ "type": "integer",
243
+ "description": "Use case ID to analyze",
244
+ },
245
+ "organization_context": {
246
+ "type": "object",
247
+ "description": "Optional organization context",
248
+ },
249
+ },
250
+ "required": ["use_case_id"],
251
+ },
252
+ ),
253
+ Tool(
254
+ name="suggest_implementation_path",
255
+ description="Suggest implementation roadmap and strategy based on use case and organizational context",
256
+ inputSchema={
257
+ "type": "object",
258
+ "properties": {
259
+ "use_case_id": {
260
+ "type": "integer",
261
+ "description": "Use case ID",
262
+ },
263
+ "organization_context": {
264
+ "type": "object",
265
+ "description": "Organization context for tailored recommendations",
266
+ },
267
+ },
268
+ "required": ["use_case_id"],
269
+ },
270
+ ),
271
+ Tool(
272
+ name="filter_by_method",
273
+ description="Find use cases using specific AI methods or techniques",
274
+ inputSchema={
275
+ "type": "object",
276
+ "properties": {
277
+ "method": {
278
+ "type": "string",
279
+ "description": "AI method or technique",
280
+ },
281
+ "min_maturity": {
282
+ "type": "string",
283
+ "description": "Minimum implementation maturity",
284
+ },
285
+ "limit": {
286
+ "type": "integer",
287
+ "description": "Maximum results",
288
+ "default": 15,
289
+ },
290
+ },
291
+ "required": ["method"],
292
+ },
293
+ ),
294
+ ]
295
+
296
+ @self.server.call_tool()
297
+ async def handle_call_tool(name: str, arguments: dict):
298
+ """Handle tool execution requests."""
299
+ if name == "search_use_cases":
300
+ return [
301
+ TextContent(
302
+ type="text",
303
+ text=json.dumps(self._search_use_cases(**arguments), indent=2),
304
+ )
305
+ ]
306
+ elif name == "filter_by_domain":
307
+ return [
308
+ TextContent(
309
+ type="text",
310
+ text=json.dumps(self._filter_by_domain(**arguments), indent=2),
311
+ )
312
+ ]
313
+ elif name == "get_use_case_details":
314
+ return [
315
+ TextContent(
316
+ type="text",
317
+ text=json.dumps(
318
+ self._get_use_case_details(**arguments), indent=2
319
+ ),
320
+ )
321
+ ]
322
+ elif name == "analyze_domain_trends":
323
+ return [
324
+ TextContent(
325
+ type="text",
326
+ text=json.dumps(
327
+ self._analyze_domain_trends(**arguments), indent=2
328
+ ),
329
+ )
330
+ ]
331
+ elif name == "recommend_similar":
332
+ return [
333
+ TextContent(
334
+ type="text",
335
+ text=json.dumps(self._recommend_similar(**arguments), indent=2),
336
+ )
337
+ ]
338
+ elif name == "estimate_complexity":
339
+ return [
340
+ TextContent(
341
+ type="text",
342
+ text=json.dumps(
343
+ self._estimate_complexity(**arguments), indent=2
344
+ ),
345
+ )
346
+ ]
347
+ elif name == "suggest_implementation_path":
348
+ return [
349
+ TextContent(
350
+ type="text",
351
+ text=json.dumps(
352
+ self._suggest_implementation_path(**arguments), indent=2
353
+ ),
354
+ )
355
+ ]
356
+ elif name == "filter_by_method":
357
+ return [
358
+ TextContent(
359
+ type="text",
360
+ text=json.dumps(self._filter_by_method(**arguments), indent=2),
361
+ )
362
+ ]
363
+ else:
364
+ raise ValueError(f"Unknown tool: {name}")
365
+
366
+ def _setup_resources(self):
367
+ """Setup MCP resources using the official SDK."""
368
+
369
+ @self.server.list_resources()
370
+ async def handle_list_resources():
371
+ """List all available AI Registry resources."""
372
+ resources = []
373
+
374
+ # Registry overview resource
375
+ resources.append(
376
+ Resource(
377
+ uri="ai-registry://overview",
378
+ name="AI Registry Overview",
379
+ description="Overview of the AI use case registry",
380
+ mimeType="application/json",
381
+ )
382
+ )
383
+
384
+ # Individual use case resources
385
+ for use_case in self.registry_data.get("use_cases", []):
386
+ use_case_id = use_case.get("use_case_id")
387
+ if use_case_id:
388
+ resources.append(
389
+ Resource(
390
+ uri=f"ai-registry://use-case/{use_case_id}",
391
+ name=f"Use Case {use_case_id}: {use_case.get('name', 'Unknown')}",
392
+ description=use_case.get("description", ""),
393
+ mimeType="application/json",
394
+ )
395
+ )
396
+
397
+ return resources
398
+
399
+ @self.server.read_resource()
400
+ async def handle_read_resource(uri: str):
401
+ """Handle resource read requests."""
402
+ if uri == "ai-registry://overview":
403
+ return [
404
+ TextContent(
405
+ type="text",
406
+ text=json.dumps(
407
+ self.registry_data.get("registry_info", {}), indent=2
408
+ ),
409
+ )
410
+ ]
411
+ elif uri.startswith("ai-registry://use-case/"):
412
+ use_case_id = int(uri.split("/")[-1])
413
+ use_case = self._get_use_case_by_id(use_case_id)
414
+ if use_case:
415
+ return [
416
+ TextContent(type="text", text=json.dumps(use_case, indent=2))
417
+ ]
418
+ else:
419
+ raise ValueError(f"Use case not found: {use_case_id}")
420
+ else:
421
+ raise ValueError(f"Unknown resource: {uri}")
422
+
423
+ # Tool implementation methods
424
+
425
+ def _search_use_cases(
426
+ self,
427
+ query: str,
428
+ domains: Optional[List[str]] = None,
429
+ methods: Optional[List[str]] = None,
430
+ limit: int = 10,
431
+ ) -> Dict[str, Any]:
432
+ """Search use cases with filters."""
433
+ use_cases = self.registry_data.get("use_cases", [])
434
+ results = []
435
+
436
+ for use_case in use_cases:
437
+ # Simple text search
438
+ score = 0.0
439
+ search_text = (
440
+ f"{use_case.get('name', '')} {use_case.get('description', '')}".lower()
441
+ )
442
+ if query.lower() in search_text:
443
+ score += 0.8
444
+
445
+ # Domain filter
446
+ if domains and use_case.get("application_domain") in domains:
447
+ score += 0.3
448
+
449
+ # Method filter
450
+ if methods:
451
+ use_case_methods = use_case.get("ai_methods", [])
452
+ if any(method in use_case_methods for method in methods):
453
+ score += 0.2
454
+
455
+ if score > 0:
456
+ results.append({"use_case": use_case, "score": score})
457
+
458
+ # Sort by score and limit results
459
+ results.sort(key=lambda x: x["score"], reverse=True)
460
+ return {"results": results[:limit], "count": len(results), "query": query}
461
+
462
+ def _filter_by_domain(
463
+ self, domain: str, status: Optional[str] = None, limit: int = 20
464
+ ) -> Dict[str, Any]:
465
+ """Filter use cases by domain."""
466
+ use_cases = self.registry_data.get("use_cases", [])
467
+ filtered = []
468
+
469
+ for use_case in use_cases:
470
+ if use_case.get("application_domain") == domain:
471
+ if not status or use_case.get("status") == status:
472
+ filtered.append(use_case)
473
+
474
+ return {"domain": domain, "count": len(filtered), "use_cases": filtered[:limit]}
475
+
476
+ def _get_use_case_details(self, use_case_id: int) -> Dict[str, Any]:
477
+ """Get detailed information for a specific use case."""
478
+ use_case = self._get_use_case_by_id(use_case_id)
479
+ if use_case:
480
+ return {
481
+ "use_case": use_case,
482
+ "similar_cases": [], # Could implement similarity search
483
+ }
484
+ else:
485
+ raise ValueError(f"Use case not found: {use_case_id}")
486
+
487
+ def _analyze_domain_trends(
488
+ self, domain: str, include_details: bool = False
489
+ ) -> Dict[str, Any]:
490
+ """Analyze trends within a specific domain."""
491
+ use_cases = [
492
+ uc
493
+ for uc in self.registry_data.get("use_cases", [])
494
+ if uc.get("application_domain") == domain
495
+ ]
496
+
497
+ # Analyze methods and statuses
498
+ methods = {}
499
+ statuses = {}
500
+
501
+ for use_case in use_cases:
502
+ for method in use_case.get("ai_methods", []):
503
+ methods[method] = methods.get(method, 0) + 1
504
+
505
+ status = use_case.get("status", "Unknown")
506
+ statuses[status] = statuses.get(status, 0) + 1
507
+
508
+ return {
509
+ "domain": domain,
510
+ "total_use_cases": len(use_cases),
511
+ "popular_methods": sorted(
512
+ methods.items(), key=lambda x: x[1], reverse=True
513
+ ),
514
+ "status_distribution": statuses,
515
+ "examples": use_cases[:3] if include_details else [],
516
+ }
517
+
518
+ def _recommend_similar(
519
+ self,
520
+ use_case_id: int,
521
+ similarity_factors: Optional[List[str]] = None,
522
+ limit: int = 5,
523
+ ) -> Dict[str, Any]:
524
+ """Find similar use cases."""
525
+ reference_case = self._get_use_case_by_id(use_case_id)
526
+ if not reference_case:
527
+ raise ValueError(f"Use case not found: {use_case_id}")
528
+
529
+ similar_cases = []
530
+ for use_case in self.registry_data.get("use_cases", []):
531
+ if use_case.get("use_case_id") != use_case_id:
532
+ similarity = self._calculate_similarity(reference_case, use_case)
533
+ if similarity > 0.3: # Threshold
534
+ similar_cases.append(
535
+ {"use_case": use_case, "similarity": similarity}
536
+ )
537
+
538
+ similar_cases.sort(key=lambda x: x["similarity"], reverse=True)
539
+ return {
540
+ "reference_use_case_id": use_case_id,
541
+ "similar_cases": similar_cases[:limit],
542
+ }
543
+
544
+ def _estimate_complexity(
545
+ self, use_case_id: int, organization_context: Optional[Dict] = None
546
+ ) -> Dict[str, Any]:
547
+ """Estimate implementation complexity."""
548
+ use_case = self._get_use_case_by_id(use_case_id)
549
+ if not use_case:
550
+ raise ValueError(f"Use case not found: {use_case_id}")
551
+
552
+ # Simple complexity scoring
553
+ score = 0
554
+ factors = []
555
+
556
+ methods = use_case.get("ai_methods", [])
557
+ for method in methods:
558
+ if "Deep Learning" in method:
559
+ score += 4
560
+ factors.append(f"AI Method: {method} (+4)")
561
+ elif "Machine Learning" in method:
562
+ score += 2
563
+ factors.append(f"AI Method: {method} (+2)")
564
+
565
+ domain = use_case.get("application_domain", "")
566
+ if domain == "Healthcare":
567
+ score += 4
568
+ factors.append(f"Domain: {domain} (+4)")
569
+
570
+ challenges = use_case.get("challenges", "")
571
+ if "privacy" in challenges.lower():
572
+ score += 3
573
+ factors.append("Challenge: privacy (+3)")
574
+
575
+ complexity_level = "Low" if score < 5 else "Medium" if score < 10 else "High"
576
+
577
+ return {
578
+ "use_case_id": use_case_id,
579
+ "complexity_score": score,
580
+ "complexity_level": complexity_level,
581
+ "scoring_factors": factors,
582
+ "estimates": {
583
+ "timeline": "6-12 months" if score < 8 else "12-18 months",
584
+ "team_size": "3-8 people" if score < 8 else "8-15 people",
585
+ "budget_category": "medium" if score < 8 else "high",
586
+ },
587
+ }
588
+
589
+ def _suggest_implementation_path(
590
+ self, use_case_id: int, organization_context: Optional[Dict] = None
591
+ ) -> Dict[str, Any]:
592
+ """Suggest implementation roadmap."""
593
+ use_case = self._get_use_case_by_id(use_case_id)
594
+ if not use_case:
595
+ raise ValueError(f"Use case not found: {use_case_id}")
596
+
597
+ phases = [
598
+ {"phase": 1, "name": "Foundation & Planning", "duration": "2-4 weeks"},
599
+ {"phase": 2, "name": "Proof of Concept", "duration": "6-8 weeks"},
600
+ {"phase": 3, "name": "Advanced Development", "duration": "12-24 weeks"},
601
+ {"phase": 4, "name": "Deployment & Monitoring", "duration": "4-8 weeks"},
602
+ ]
603
+
604
+ recommendations = [
605
+ "Start with a well-defined proof of concept",
606
+ "Ensure data quality and availability early",
607
+ "Plan for change management and user adoption",
608
+ ]
609
+
610
+ # Domain-specific recommendations
611
+ domain = use_case.get("application_domain", "")
612
+ if domain == "Healthcare":
613
+ recommendations.extend(
614
+ [
615
+ "Ensure HIPAA compliance and data privacy measures",
616
+ "Plan for regulatory approval processes",
617
+ "Consider partnering with medical AI specialists",
618
+ ]
619
+ )
620
+
621
+ return {
622
+ "use_case_id": use_case_id,
623
+ "use_case_name": use_case.get("name", ""),
624
+ "implementation_phases": phases,
625
+ "key_recommendations": recommendations,
626
+ }
627
+
628
+ def _filter_by_method(
629
+ self, method: str, min_maturity: Optional[str] = None, limit: int = 15
630
+ ) -> Dict[str, Any]:
631
+ """Filter use cases by AI method."""
632
+ use_cases = self.registry_data.get("use_cases", [])
633
+ filtered = []
634
+
635
+ for use_case in use_cases:
636
+ methods = use_case.get("ai_methods", [])
637
+ if any(method.lower() in m.lower() for m in methods):
638
+ if not min_maturity or self._check_maturity(
639
+ use_case.get("status", ""), min_maturity
640
+ ):
641
+ filtered.append(use_case)
642
+
643
+ return {"method": method, "count": len(filtered), "use_cases": filtered[:limit]}
644
+
645
+ # Helper methods
646
+
647
+ def _get_use_case_by_id(self, use_case_id: int) -> Optional[Dict[str, Any]]:
648
+ """Get use case by ID."""
649
+ for use_case in self.registry_data.get("use_cases", []):
650
+ if use_case.get("use_case_id") == use_case_id:
651
+ return use_case
652
+ return None
653
+
654
+ def _calculate_similarity(
655
+ self, case1: Dict[str, Any], case2: Dict[str, Any]
656
+ ) -> float:
657
+ """Calculate similarity between two use cases."""
658
+ score = 0.0
659
+
660
+ # Domain similarity
661
+ if case1.get("application_domain") == case2.get("application_domain"):
662
+ score += 0.4
663
+
664
+ # Method similarity
665
+ methods1 = set(case1.get("ai_methods", []))
666
+ methods2 = set(case2.get("ai_methods", []))
667
+ if methods1 and methods2:
668
+ overlap = len(methods1.intersection(methods2))
669
+ total = len(methods1.union(methods2))
670
+ score += 0.6 * (overlap / total)
671
+
672
+ return score
673
+
674
+ def _check_maturity(self, status: str, min_maturity: str) -> bool:
675
+ """Check if status meets minimum maturity requirement."""
676
+ maturity_order = ["Idea", "PoC", "PoB", "Production"]
677
+ try:
678
+ status_level = maturity_order.index(status)
679
+ min_level = maturity_order.index(min_maturity)
680
+ return status_level >= min_level
681
+ except ValueError:
682
+ return True # If unknown status, include it
683
+
684
+ async def run_stdio(self):
685
+ """Run the server with stdio transport."""
686
+ from mcp.server.stdio import stdio_server
687
+
688
+ async with stdio_server() as (read_stream, write_stream):
689
+ await self.server.run(
690
+ read_stream, write_stream, self.server.create_initialization_options()
691
+ )
692
+
693
+
694
+ async def main():
695
+ """Main entry point for running the AI Registry MCP server."""
696
+ # Get registry file from environment or use default
697
+ registry_file = os.environ.get(
698
+ "REGISTRY_FILE", "research/combined_ai_registry.json"
699
+ )
700
+
701
+ server = AIRegistryServer(registry_file)
702
+ await server.run_stdio()
703
+
704
+
705
+ if __name__ == "__main__":
706
+ asyncio.run(main())
707
+
708
+
709
+ # For module execution
710
+ def run_server():
711
+ """Entry point for python -m kailash.mcp.ai_registry_server"""
712
+ asyncio.run(main())