kailash 0.6.2__py3-none-any.whl → 0.6.3__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.
- kailash/__init__.py +1 -1
- kailash/{mcp → mcp_server}/__init__.py +12 -7
- kailash/{mcp → mcp_server}/ai_registry_server.py +2 -2
- kailash/{mcp/server_enhanced.py → mcp_server/server.py} +231 -48
- kailash/{mcp → mcp_server}/servers/ai_registry.py +2 -2
- kailash/{mcp → mcp_server}/utils/__init__.py +1 -6
- kailash/middleware/mcp/client_integration.py +1 -1
- kailash/middleware/mcp/enhanced_server.py +2 -2
- kailash/nodes/ai/iterative_llm_agent.py +1 -1
- kailash/nodes/ai/llm_agent.py +3 -3
- {kailash-0.6.2.dist-info → kailash-0.6.3.dist-info}/METADATA +2 -2
- {kailash-0.6.2.dist-info → kailash-0.6.3.dist-info}/RECORD +22 -23
- kailash/mcp/server.py +0 -292
- /kailash/{mcp → mcp_server}/client.py +0 -0
- /kailash/{mcp → mcp_server}/client_new.py +0 -0
- /kailash/{mcp → mcp_server}/utils/cache.py +0 -0
- /kailash/{mcp → mcp_server}/utils/config.py +0 -0
- /kailash/{mcp → mcp_server}/utils/formatters.py +0 -0
- /kailash/{mcp → mcp_server}/utils/metrics.py +0 -0
- {kailash-0.6.2.dist-info → kailash-0.6.3.dist-info}/WHEEL +0 -0
- {kailash-0.6.2.dist-info → kailash-0.6.3.dist-info}/entry_points.txt +0 -0
- {kailash-0.6.2.dist-info → kailash-0.6.3.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.6.2.dist-info → kailash-0.6.3.dist-info}/top_level.txt +0 -0
kailash/__init__.py
CHANGED
@@ -12,8 +12,8 @@ Design Philosophy:
|
|
12
12
|
|
13
13
|
Key Components:
|
14
14
|
- MCPClient: Connects to MCP servers for tool and resource access
|
15
|
-
- MCPServer:
|
16
|
-
-
|
15
|
+
- MCPServer: Main production-ready server with all features
|
16
|
+
- MCPServerBase: Abstract base class for custom server implementations
|
17
17
|
|
18
18
|
Upstream Dependencies:
|
19
19
|
- Official Anthropic MCP Python SDK for protocol implementation
|
@@ -28,26 +28,31 @@ Downstream Consumers:
|
|
28
28
|
Examples:
|
29
29
|
Basic MCP client usage:
|
30
30
|
|
31
|
-
>>> from kailash.
|
31
|
+
>>> from kailash.mcp_server import MCPClient
|
32
32
|
>>> client = MCPClient()
|
33
33
|
>>> tools = await client.discover_tools(server_config)
|
34
34
|
>>> result = await client.call_tool(server_config, "search", {"query": "AI"})
|
35
35
|
|
36
36
|
Simple MCP server creation:
|
37
37
|
|
38
|
-
>>> from kailash.
|
39
|
-
>>> server =
|
38
|
+
>>> from kailash.mcp_server import MCPServer
|
39
|
+
>>> server = MCPServer("my-tools")
|
40
40
|
>>> @server.tool()
|
41
41
|
... def calculate(a: int, b: int) -> int:
|
42
42
|
... return a + b
|
43
|
-
>>> server.
|
43
|
+
>>> server.run()
|
44
44
|
"""
|
45
45
|
|
46
46
|
from .client import MCPClient
|
47
|
-
|
47
|
+
|
48
|
+
# For backward compatibility
|
49
|
+
from .server import EnhancedMCPServer, MCPServer, MCPServerBase, SimpleMCPServer
|
48
50
|
|
49
51
|
__all__ = [
|
50
52
|
"MCPClient",
|
51
53
|
"MCPServer",
|
54
|
+
"MCPServerBase",
|
55
|
+
# Backward compatibility
|
52
56
|
"SimpleMCPServer",
|
57
|
+
"EnhancedMCPServer",
|
53
58
|
]
|
@@ -5,7 +5,7 @@ AI Registry MCP Server using Anthropic's Official MCP Python SDK.
|
|
5
5
|
This creates a real MCP server that exposes AI Registry tools following
|
6
6
|
the actual Model Context Protocol specification.
|
7
7
|
|
8
|
-
Run as: python -m kailash.
|
8
|
+
Run as: python -m kailash.mcp_server.ai_registry_server
|
9
9
|
"""
|
10
10
|
|
11
11
|
import asyncio
|
@@ -708,5 +708,5 @@ if __name__ == "__main__":
|
|
708
708
|
|
709
709
|
# For module execution
|
710
710
|
def run_server():
|
711
|
-
"""Entry point for python -m kailash.
|
711
|
+
"""Entry point for python -m kailash.mcp_server.ai_registry_server"""
|
712
712
|
asyncio.run(main())
|
@@ -1,16 +1,39 @@
|
|
1
1
|
"""
|
2
|
-
|
3
|
-
|
4
|
-
This module provides
|
5
|
-
|
6
|
-
|
2
|
+
MCP Server Framework with production-ready capabilities.
|
3
|
+
|
4
|
+
This module provides both basic and enhanced MCP server implementations using
|
5
|
+
the official FastMCP framework from Anthropic. Servers run as long-lived
|
6
|
+
services that expose tools, resources, and prompts to MCP clients.
|
7
|
+
|
8
|
+
Basic Usage:
|
9
|
+
Abstract base class for custom servers:
|
10
|
+
|
11
|
+
>>> class MyServer(MCPServerBase):
|
12
|
+
... def setup(self):
|
13
|
+
... @self.add_tool()
|
14
|
+
... def calculate(a: int, b: int) -> int:
|
15
|
+
... return a + b
|
16
|
+
>>> server = MyServer("calculator")
|
17
|
+
>>> server.start()
|
18
|
+
|
19
|
+
Production Usage:
|
20
|
+
Main server with all production features:
|
21
|
+
|
22
|
+
>>> from kailash.mcp_server import MCPServer
|
23
|
+
>>> server = MCPServer("my-server", enable_cache=True)
|
24
|
+
>>> @server.tool(cache_key="search", cache_ttl=600)
|
25
|
+
... def search(query: str) -> dict:
|
26
|
+
... return {"results": f"Found data for {query}"}
|
27
|
+
>>> server.run()
|
7
28
|
"""
|
8
29
|
|
9
30
|
import asyncio
|
10
31
|
import functools
|
11
32
|
import logging
|
33
|
+
from abc import ABC, abstractmethod
|
34
|
+
from collections.abc import Callable
|
12
35
|
from pathlib import Path
|
13
|
-
from typing import Any,
|
36
|
+
from typing import Any, Dict, Optional, TypeVar, Union
|
14
37
|
|
15
38
|
from .utils import CacheManager, ConfigManager, MetricsCollector, format_response
|
16
39
|
|
@@ -19,18 +42,199 @@ logger = logging.getLogger(__name__)
|
|
19
42
|
F = TypeVar("F", bound=Callable[..., Any])
|
20
43
|
|
21
44
|
|
45
|
+
class MCPServerBase(ABC):
|
46
|
+
"""Base class for MCP servers using FastMCP.
|
47
|
+
|
48
|
+
This provides a framework for creating MCP servers that expose
|
49
|
+
tools, resources, and prompts via the Model Context Protocol.
|
50
|
+
|
51
|
+
Examples:
|
52
|
+
Creating a custom server:
|
53
|
+
|
54
|
+
>>> class MyServer(MCPServerBase):
|
55
|
+
... def setup(self):
|
56
|
+
... @self.add_tool()
|
57
|
+
... def search(query: str) -> str:
|
58
|
+
... return f"Results for: {query}"
|
59
|
+
... @self.add_resource("data://example")
|
60
|
+
... def get_example():
|
61
|
+
... return "Example data"
|
62
|
+
>>> server = MyServer("my-server", port=8080)
|
63
|
+
>>> server.start() # Runs until stopped
|
64
|
+
"""
|
65
|
+
|
66
|
+
def __init__(self, name: str, port: int = 8080, host: str = "localhost"):
|
67
|
+
"""Initialize the MCP server.
|
68
|
+
|
69
|
+
Args:
|
70
|
+
name: Name of the server.
|
71
|
+
port: Port to listen on (default: 8080).
|
72
|
+
host: Host to bind to (default: "localhost").
|
73
|
+
"""
|
74
|
+
self.name = name
|
75
|
+
self.port = port
|
76
|
+
self.host = host
|
77
|
+
self._mcp = None
|
78
|
+
self._running = False
|
79
|
+
|
80
|
+
@abstractmethod
|
81
|
+
def setup(self):
|
82
|
+
"""Setup server tools, resources, and prompts.
|
83
|
+
|
84
|
+
This method should be implemented by subclasses to define
|
85
|
+
the server's capabilities using decorators.
|
86
|
+
|
87
|
+
Note:
|
88
|
+
Use @self.add_tool(), @self.add_resource(uri), and
|
89
|
+
@self.add_prompt(name) decorators to register capabilities.
|
90
|
+
"""
|
91
|
+
|
92
|
+
def add_tool(self):
|
93
|
+
"""Decorator to add a tool to the server.
|
94
|
+
|
95
|
+
Returns:
|
96
|
+
Function decorator for registering tools.
|
97
|
+
|
98
|
+
Examples:
|
99
|
+
>>> @server.add_tool()
|
100
|
+
... def calculate(a: int, b: int) -> int:
|
101
|
+
... '''Add two numbers'''
|
102
|
+
... return a + b
|
103
|
+
"""
|
104
|
+
|
105
|
+
def decorator(func: Callable):
|
106
|
+
if self._mcp is None:
|
107
|
+
self._init_mcp()
|
108
|
+
|
109
|
+
# Use FastMCP's tool decorator
|
110
|
+
return self._mcp.tool()(func)
|
111
|
+
|
112
|
+
return decorator
|
113
|
+
|
114
|
+
def add_resource(self, uri: str):
|
115
|
+
"""Decorator to add a resource to the server.
|
116
|
+
|
117
|
+
Args:
|
118
|
+
uri: URI pattern for the resource (supports wildcards).
|
119
|
+
|
120
|
+
Returns:
|
121
|
+
Function decorator for registering resources.
|
122
|
+
|
123
|
+
Examples:
|
124
|
+
>>> @server.add_resource("file:///data/*")
|
125
|
+
... def get_file(path: str) -> str:
|
126
|
+
... return f"Content of {path}"
|
127
|
+
"""
|
128
|
+
|
129
|
+
def decorator(func: Callable):
|
130
|
+
if self._mcp is None:
|
131
|
+
self._init_mcp()
|
132
|
+
|
133
|
+
# Use FastMCP's resource decorator
|
134
|
+
return self._mcp.resource(uri)(func)
|
135
|
+
|
136
|
+
return decorator
|
137
|
+
|
138
|
+
def add_prompt(self, name: str):
|
139
|
+
"""Decorator to add a prompt template to the server.
|
140
|
+
|
141
|
+
Args:
|
142
|
+
name: Name of the prompt.
|
143
|
+
|
144
|
+
Returns:
|
145
|
+
Function decorator for registering prompts.
|
146
|
+
|
147
|
+
Examples:
|
148
|
+
>>> @server.add_prompt("analyze")
|
149
|
+
... def analyze_prompt(data: str) -> str:
|
150
|
+
... return f"Please analyze the following data: {data}"
|
151
|
+
"""
|
152
|
+
|
153
|
+
def decorator(func: Callable):
|
154
|
+
if self._mcp is None:
|
155
|
+
self._init_mcp()
|
156
|
+
|
157
|
+
# Use FastMCP's prompt decorator
|
158
|
+
return self._mcp.prompt(name)(func)
|
159
|
+
|
160
|
+
return decorator
|
161
|
+
|
162
|
+
def _init_mcp(self):
|
163
|
+
"""Initialize the FastMCP instance."""
|
164
|
+
try:
|
165
|
+
from mcp.server import FastMCP
|
166
|
+
|
167
|
+
self._mcp = FastMCP(self.name)
|
168
|
+
except ImportError:
|
169
|
+
logger.error(
|
170
|
+
"FastMCP not available. Install with: pip install 'mcp[server]'"
|
171
|
+
)
|
172
|
+
raise
|
173
|
+
|
174
|
+
def start(self):
|
175
|
+
"""Start the MCP server.
|
176
|
+
|
177
|
+
This runs the server as a long-lived process until stopped.
|
178
|
+
|
179
|
+
Raises:
|
180
|
+
ImportError: If FastMCP is not available.
|
181
|
+
Exception: If server fails to start.
|
182
|
+
"""
|
183
|
+
if self._mcp is None:
|
184
|
+
self._init_mcp()
|
185
|
+
|
186
|
+
# Run setup to register tools/resources
|
187
|
+
self.setup()
|
188
|
+
|
189
|
+
logger.info(f"Starting MCP server '{self.name}' on {self.host}:{self.port}")
|
190
|
+
self._running = True
|
191
|
+
|
192
|
+
try:
|
193
|
+
# Run the FastMCP server
|
194
|
+
logger.info("Running FastMCP server in stdio mode")
|
195
|
+
self._mcp.run()
|
196
|
+
except Exception as e:
|
197
|
+
logger.error(f"Failed to start server: {e}")
|
198
|
+
raise
|
199
|
+
finally:
|
200
|
+
self._running = False
|
201
|
+
|
202
|
+
def stop(self):
|
203
|
+
"""Stop the MCP server."""
|
204
|
+
logger.info(f"Stopping MCP server '{self.name}'")
|
205
|
+
self._running = False
|
206
|
+
# In a real implementation, we'd need to handle graceful shutdown
|
207
|
+
|
208
|
+
|
22
209
|
class EnhancedMCPServer:
|
23
210
|
"""
|
24
|
-
Production-ready MCP server
|
211
|
+
Production-ready MCP server (available as SimpleMCPServer).
|
25
212
|
|
26
|
-
|
27
|
-
|
213
|
+
This is the main concrete MCP server implementation with all production
|
214
|
+
features available. Features can be enabled/disabled as needed.
|
215
|
+
|
216
|
+
Features available:
|
217
|
+
- Caching with TTL support (enable_cache=True)
|
218
|
+
- Metrics collection and monitoring (enable_metrics=True)
|
219
|
+
- Response formatting utilities (enable_formatting=True)
|
28
220
|
- Hierarchical configuration management
|
29
|
-
- Metrics collection and monitoring
|
30
|
-
- Response formatting utilities
|
31
221
|
- Error handling and logging
|
32
222
|
|
33
|
-
|
223
|
+
Examples:
|
224
|
+
Basic usage (recommended):
|
225
|
+
>>> from kailash.mcp_server import MCPServer
|
226
|
+
>>> server = MCPServer("my-server")
|
227
|
+
>>> @server.tool()
|
228
|
+
... def search(query: str) -> dict:
|
229
|
+
... return {"results": f"Found: {query}"}
|
230
|
+
>>> server.run()
|
231
|
+
|
232
|
+
With production features enabled:
|
233
|
+
>>> server = MCPServer("my-server", enable_cache=True, enable_metrics=True)
|
234
|
+
>>> @server.tool(cache_key="search", cache_ttl=600)
|
235
|
+
... def search(query: str) -> dict:
|
236
|
+
... return {"results": f"Found: {query}"}
|
237
|
+
>>> server.run()
|
34
238
|
"""
|
35
239
|
|
36
240
|
def __init__(
|
@@ -104,15 +308,21 @@ class EnhancedMCPServer:
|
|
104
308
|
return
|
105
309
|
|
106
310
|
try:
|
107
|
-
from mcp.server
|
311
|
+
# Now we can safely import from external mcp.server (no namespace collision)
|
312
|
+
from mcp.server import FastMCP
|
108
313
|
|
109
314
|
self._mcp = FastMCP(self.name)
|
110
315
|
logger.info(f"Initialized FastMCP server: {self.name}")
|
111
|
-
except ImportError:
|
316
|
+
except ImportError as e:
|
317
|
+
logger.error(
|
318
|
+
f"FastMCP import failed with: {e}. Details: {type(e).__name__}"
|
319
|
+
)
|
112
320
|
logger.error(
|
113
321
|
"FastMCP not available. Install with: pip install 'mcp[server]'"
|
114
322
|
)
|
115
|
-
raise
|
323
|
+
raise ImportError(
|
324
|
+
"FastMCP not available. Install with: pip install 'mcp[server]'"
|
325
|
+
) from e
|
116
326
|
|
117
327
|
def tool(
|
118
328
|
self,
|
@@ -413,37 +623,10 @@ class EnhancedMCPServer:
|
|
413
623
|
self._running = False
|
414
624
|
|
415
625
|
|
416
|
-
#
|
626
|
+
# Clean public API design:
|
627
|
+
# - MCPServerBase: Abstract base for custom implementations (e.g., AIRegistryServer)
|
628
|
+
# - MCPServer: Main concrete server with all production features
|
629
|
+
# - SimpleMCPServer: Alias for backward compatibility
|
630
|
+
# - EnhancedMCPServer: Alias for backward compatibility
|
417
631
|
MCPServer = EnhancedMCPServer
|
418
|
-
|
419
|
-
|
420
|
-
class SimpleMCPServer(EnhancedMCPServer):
|
421
|
-
"""
|
422
|
-
Simplified MCP server with minimal configuration.
|
423
|
-
|
424
|
-
This inherits all enhanced capabilities but disables some features
|
425
|
-
by default for simpler use cases.
|
426
|
-
"""
|
427
|
-
|
428
|
-
def __init__(self, name: str, description: str = ""):
|
429
|
-
"""
|
430
|
-
Initialize simple MCP server.
|
431
|
-
|
432
|
-
Args:
|
433
|
-
name: Server name
|
434
|
-
description: Server description
|
435
|
-
"""
|
436
|
-
# Initialize with some features disabled for simplicity
|
437
|
-
super().__init__(
|
438
|
-
name=name,
|
439
|
-
enable_cache=False, # Disable cache by default
|
440
|
-
enable_metrics=False, # Disable metrics by default
|
441
|
-
enable_formatting=True, # Keep formatting for better output
|
442
|
-
)
|
443
|
-
|
444
|
-
self.description = description
|
445
|
-
|
446
|
-
# Update config for simple use
|
447
|
-
self.config.update(
|
448
|
-
{"server": {"name": name, "description": description, "version": "1.0.0"}}
|
449
|
-
)
|
632
|
+
SimpleMCPServer = EnhancedMCPServer
|
@@ -9,10 +9,10 @@ import os
|
|
9
9
|
from pathlib import Path
|
10
10
|
from typing import Any
|
11
11
|
|
12
|
-
from kailash.
|
12
|
+
from kailash.mcp_server.server import MCPServerBase
|
13
13
|
|
14
14
|
|
15
|
-
class AIRegistryServer(
|
15
|
+
class AIRegistryServer(MCPServerBase):
|
16
16
|
"""MCP server for AI use case registry.
|
17
17
|
|
18
18
|
Provides tools and resources for exploring AI use cases from
|
@@ -10,12 +10,7 @@ This module provides production-ready utilities for MCP servers including:
|
|
10
10
|
|
11
11
|
from .cache import CacheManager, LRUCache, cached_query
|
12
12
|
from .config import ConfigManager
|
13
|
-
from .formatters import
|
14
|
-
format_response,
|
15
|
-
json_formatter,
|
16
|
-
markdown_formatter,
|
17
|
-
search_formatter,
|
18
|
-
)
|
13
|
+
from .formatters import format_response, json_formatter, markdown_formatter, search_formatter
|
19
14
|
from .metrics import MetricsCollector
|
20
15
|
|
21
16
|
__all__ = [
|
@@ -24,8 +24,8 @@ from kailash.workflow.builder import WorkflowBuilder
|
|
24
24
|
|
25
25
|
# Import existing Kailash MCP components
|
26
26
|
try:
|
27
|
-
from kailash.
|
28
|
-
from kailash.
|
27
|
+
from kailash.mcp_server import MCPServer, SimpleMCPServer
|
28
|
+
from kailash.mcp_server.utils import CacheManager, ConfigManager, MetricsCollector
|
29
29
|
|
30
30
|
_KAILASH_MCP_AVAILABLE = True
|
31
31
|
except ImportError:
|
@@ -457,7 +457,7 @@ class IterativeLLMAgentNode(LLMAgentNode):
|
|
457
457
|
try:
|
458
458
|
# Ensure MCP client is initialized
|
459
459
|
if not hasattr(self, "_mcp_client"):
|
460
|
-
from kailash.
|
460
|
+
from kailash.mcp_server import MCPClient
|
461
461
|
|
462
462
|
self._mcp_client = MCPClient()
|
463
463
|
|
kailash/nodes/ai/llm_agent.py
CHANGED
@@ -985,7 +985,7 @@ class LLMAgentNode(Node):
|
|
985
985
|
import asyncio
|
986
986
|
from datetime import datetime
|
987
987
|
|
988
|
-
from kailash.
|
988
|
+
from kailash.mcp_server import MCPClient
|
989
989
|
|
990
990
|
# Initialize MCP client if not already done
|
991
991
|
if not hasattr(self, "_mcp_client"):
|
@@ -1182,7 +1182,7 @@ class LLMAgentNode(Node):
|
|
1182
1182
|
|
1183
1183
|
if use_real_mcp:
|
1184
1184
|
try:
|
1185
|
-
from kailash.
|
1185
|
+
from kailash.mcp_server import MCPClient
|
1186
1186
|
|
1187
1187
|
# Initialize MCP client if not already done
|
1188
1188
|
if not hasattr(self, "_mcp_client"):
|
@@ -1767,7 +1767,7 @@ class LLMAgentNode(Node):
|
|
1767
1767
|
server_config = mcp_tool.get("function", {}).get("mcp_server_config", {})
|
1768
1768
|
|
1769
1769
|
try:
|
1770
|
-
from kailash.
|
1770
|
+
from kailash.mcp_server import MCPClient
|
1771
1771
|
|
1772
1772
|
# Initialize MCP client if not already done
|
1773
1773
|
if not hasattr(self, "_mcp_client"):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: kailash
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.3
|
4
4
|
Summary: Python SDK for the Kailash container-node architecture
|
5
5
|
Home-page: https://github.com/integrum/kailash-python-sdk
|
6
6
|
Author: Integrum
|
@@ -21,7 +21,7 @@ Requires-Dist: matplotlib>=3.5
|
|
21
21
|
Requires-Dist: pyyaml>=6.0
|
22
22
|
Requires-Dist: click>=8.0
|
23
23
|
Requires-Dist: pytest>=8.3.5
|
24
|
-
Requires-Dist: mcp[cli]>=1.9.2
|
24
|
+
Requires-Dist: mcp[cli,server]>=1.9.2
|
25
25
|
Requires-Dist: pandas>=2.2.3
|
26
26
|
Requires-Dist: numpy>=2.2.5
|
27
27
|
Requires-Dist: scipy>=1.15.3
|
@@ -1,4 +1,4 @@
|
|
1
|
-
kailash/__init__.py,sha256=
|
1
|
+
kailash/__init__.py,sha256=8W7LrVttYlpEMHu8_N4a5CilyUWMORrc8rnCbaAJ8HU,1724
|
2
2
|
kailash/__main__.py,sha256=vr7TVE5o16V6LsTmRFKG6RDKUXHpIWYdZ6Dok2HkHnI,198
|
3
3
|
kailash/access_control.py,sha256=2ctdRFeSeu-d7DU04Aovxh6Rt_4t3IyQfkKEjTeQiMM,25519
|
4
4
|
kailash/access_control_abac.py,sha256=FPfa_8PuDP3AxTjdWfiH3ntwWO8NodA0py9W8SE5dno,30263
|
@@ -43,18 +43,17 @@ kailash/gateway/api.py,sha256=xpK8PIamsqQPpKAJwacyV7RA_Snjv2pc_0ljnnU9Oy4,9534
|
|
43
43
|
kailash/gateway/enhanced_gateway.py,sha256=IlN1XV01FQrF4rGcq_z9LE4uUHAAAQoVsRNToXENen0,13399
|
44
44
|
kailash/gateway/resource_resolver.py,sha256=IC1dceiKfjfUWToYCIBcrUapuR3LlDG6RJ4o7haLY10,7746
|
45
45
|
kailash/gateway/security.py,sha256=kf4Quf6u7dqhs80fQQ982eHbRb4weDKG0DaYNeKntT4,7557
|
46
|
-
kailash/
|
47
|
-
kailash/
|
48
|
-
kailash/
|
49
|
-
kailash/
|
50
|
-
kailash/
|
51
|
-
kailash/
|
52
|
-
kailash/
|
53
|
-
kailash/
|
54
|
-
kailash/
|
55
|
-
kailash/
|
56
|
-
kailash/
|
57
|
-
kailash/mcp/utils/metrics.py,sha256=MNUjWGQyq1EGdeqzAKCCZJNgcWHOyaYAV8MlS2cb-4k,13754
|
46
|
+
kailash/mcp_server/__init__.py,sha256=ETEeaRTqj2xeX07MyaRgcPiaomdLoJ24iNmRbRjJQok,1953
|
47
|
+
kailash/mcp_server/ai_registry_server.py,sha256=BkkZcohRyGlSbiUkpRTaIA6M_yJUgtgtMda-dvbT86s,28118
|
48
|
+
kailash/mcp_server/client.py,sha256=sTouSiuiu1nbahMXSWcP8-mr1k7cqdBCzSxm8G7le-s,16058
|
49
|
+
kailash/mcp_server/client_new.py,sha256=YU671JvAM0uvuX0uhGZCIKI8co3fqz0cs6HqLZ59Xyo,10285
|
50
|
+
kailash/mcp_server/server.py,sha256=z-72J5MKq98_j7zwo0HJMbMI9bp5yuNpyfIzD9N23yw,20600
|
51
|
+
kailash/mcp_server/servers/ai_registry.py,sha256=IdF_keUuJlMsvjLjSAykxxbm46K4qA7eCj7T-lYSrzk,10007
|
52
|
+
kailash/mcp_server/utils/__init__.py,sha256=VjGFpvugTYUxoNgtwVEKkmrkVS3iZ_kIbP4jR1PRM6E,750
|
53
|
+
kailash/mcp_server/utils/cache.py,sha256=dLEseovPaXL4lRzMSw7tqd3tJHwnWfhdZ-HKGyScJXI,8414
|
54
|
+
kailash/mcp_server/utils/config.py,sha256=DyZxgdy3vqI5pwhQ_E-42mhueVGNHiuOtTUOrM9HC_U,8124
|
55
|
+
kailash/mcp_server/utils/formatters.py,sha256=D-2j1nvmprApiUI13HWY-L2_WPSAcJDtVdHcshAuOdo,9740
|
56
|
+
kailash/mcp_server/utils/metrics.py,sha256=MNUjWGQyq1EGdeqzAKCCZJNgcWHOyaYAV8MlS2cb-4k,13754
|
58
57
|
kailash/middleware/__init__.py,sha256=ZGo0qujL-qWn82nIrojY96N1rMPTWFKHumW6CGGpb4Y,10409
|
59
58
|
kailash/middleware/auth/__init__.py,sha256=VkKM8H-zVFx2PLGL7kyxE2IfSiV1HiwveSysbmxMcg0,2077
|
60
59
|
kailash/middleware/auth/access_control.py,sha256=2FwQjp_fZm2fg-V_CIgAN69GGL9YwyZwsbQis0hbW7I,14848
|
@@ -87,8 +86,8 @@ kailash/middleware/gateway/durable_gateway.py,sha256=EsIgMNxS_no2W40AXDyE7FmVdnG
|
|
87
86
|
kailash/middleware/gateway/durable_request.py,sha256=SCnp-bF0tQX9oahr9reqcZjJ_YhyJkeYYl-un9rJ6lo,15437
|
88
87
|
kailash/middleware/gateway/event_store.py,sha256=A3Kh2MhVVPbXWvjeo550SqEGPiJYyspAfu6Gv7UZzo4,16131
|
89
88
|
kailash/middleware/mcp/__init__.py,sha256=EdZB8zOMSBEEmudRzs8ksz9QZJYWQMEx7Tm1MOwIWnI,922
|
90
|
-
kailash/middleware/mcp/client_integration.py,sha256=
|
91
|
-
kailash/middleware/mcp/enhanced_server.py,sha256=
|
89
|
+
kailash/middleware/mcp/client_integration.py,sha256=dY1RmX-g5E6JzUFuWxk7viuOYIh8bMwoUSvHQMVEsYk,18265
|
90
|
+
kailash/middleware/mcp/enhanced_server.py,sha256=vVd7WE95c-5861VtKfmTZ91iUWFRw-aKEKwHlu6edQo,18467
|
92
91
|
kailash/nodes/__init__.py,sha256=E6CEp1ooq4GgFhKtwVAczOhPt5N3x-AVQ-R0n3_IFyA,936
|
93
92
|
kailash/nodes/base.py,sha256=Fu9c2I5k_Ke192y4fj2NVhf-Y_I0nPr0sDE1zMSRCJY,55417
|
94
93
|
kailash/nodes/base_async.py,sha256=mpntaeFMbUYLIyTvjsb221mXckx_H2dGX2LhxeKhhfA,6569
|
@@ -112,8 +111,8 @@ kailash/nodes/ai/agents.py,sha256=CRA3cdapQjpuvOniXUh6ZVWAlRxUIepVw1BROW6QzdY,20
|
|
112
111
|
kailash/nodes/ai/ai_providers.py,sha256=XeDIaYH7PrX8frWCVV6CYFNQXFjHX_61T3eR1yullqs,65355
|
113
112
|
kailash/nodes/ai/embedding_generator.py,sha256=rsos3B6oWrgGTMIbwSWIBzGH9kq3SFVD_-bEDrujBRs,31860
|
114
113
|
kailash/nodes/ai/intelligent_agent_orchestrator.py,sha256=xw44C-CkcNH3SVmEJ49o4oNV3o4ZqjLE9aLpggwoIXs,83021
|
115
|
-
kailash/nodes/ai/iterative_llm_agent.py,sha256=
|
116
|
-
kailash/nodes/ai/llm_agent.py,sha256
|
114
|
+
kailash/nodes/ai/iterative_llm_agent.py,sha256=14SxTRGGGYRqNC0SFMaKAFplUcsQXAVzXKcjri_0oWM,52891
|
115
|
+
kailash/nodes/ai/llm_agent.py,sha256=0N5NU2HLwbh2_zFxrgwq2FlkVS6fifpEcMSI0BGX7ZQ,82198
|
117
116
|
kailash/nodes/ai/models.py,sha256=wsEeUTuegy87mnLtKgSTg7ggCXvC1n3MsL-iZ4qujHs,16393
|
118
117
|
kailash/nodes/ai/self_organizing.py,sha256=M7yCLkN4I1JCNU7PWuwrqwQSlaG9MJVxYIR44TV52MM,62877
|
119
118
|
kailash/nodes/ai/vision_utils.py,sha256=OHD9cVH_mq0WpJyQkNTj_mpipIVWfSV_bF9eA6CdyeA,4166
|
@@ -271,9 +270,9 @@ kailash/workflow/state.py,sha256=UTZxs5-Ona6uvBhx1__i6-RX8gB4qazkBIWE7uyRmWQ,760
|
|
271
270
|
kailash/workflow/templates.py,sha256=98EN5H4fO9b4xeczk20Hu5L8hNcAuRQNGayT6vnZYCw,48540
|
272
271
|
kailash/workflow/validation.py,sha256=JIbIajWVIaWHSvWtgZ4WUVJaBaUOCz5B9cyTwM--dL4,33060
|
273
272
|
kailash/workflow/visualization.py,sha256=ICMWCWqh5fOQ7eJygbvu2PMWHxe-H5_0epwdZuz8cMw,19737
|
274
|
-
kailash-0.6.
|
275
|
-
kailash-0.6.
|
276
|
-
kailash-0.6.
|
277
|
-
kailash-0.6.
|
278
|
-
kailash-0.6.
|
279
|
-
kailash-0.6.
|
273
|
+
kailash-0.6.3.dist-info/licenses/LICENSE,sha256=Axe6g7bTrJkToK9h9j2SpRUKKNaDZDCo2lQ2zPxCE6s,1065
|
274
|
+
kailash-0.6.3.dist-info/METADATA,sha256=PH0D-ORbBHT7eJjuIEMbrcr1CWNlQpY36Ncy4jGJ-wg,25932
|
275
|
+
kailash-0.6.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
276
|
+
kailash-0.6.3.dist-info/entry_points.txt,sha256=M_q3b8PG5W4XbhSgESzIJjh3_4OBKtZFYFsOdkr2vO4,45
|
277
|
+
kailash-0.6.3.dist-info/top_level.txt,sha256=z7GzH2mxl66498pVf5HKwo5wwfPtt9Aq95uZUpH6JV0,8
|
278
|
+
kailash-0.6.3.dist-info/RECORD,,
|
kailash/mcp/server.py
DELETED
@@ -1,292 +0,0 @@
|
|
1
|
-
"""MCP Server Framework using official Anthropic SDK.
|
2
|
-
|
3
|
-
This module provides a comprehensive framework for creating MCP servers using
|
4
|
-
the official FastMCP framework from Anthropic. Servers run as long-lived
|
5
|
-
services that expose tools, resources, and prompts to MCP clients, enabling
|
6
|
-
dynamic capability extension for AI workflows.
|
7
|
-
|
8
|
-
Note:
|
9
|
-
This module requires the FastMCP framework to be installed.
|
10
|
-
Install with: pip install 'mcp[server]'
|
11
|
-
|
12
|
-
Examples:
|
13
|
-
Basic server with tools:
|
14
|
-
|
15
|
-
>>> from kailash.mcp.server import MCPServer
|
16
|
-
>>> class MyServer(MCPServer):
|
17
|
-
... def setup(self):
|
18
|
-
... @self.add_tool()
|
19
|
-
... def calculate(a: int, b: int) -> int:
|
20
|
-
... return a + b
|
21
|
-
>>> server = MyServer("calculator", port=8080)
|
22
|
-
>>> server.start()
|
23
|
-
|
24
|
-
Quick server creation:
|
25
|
-
|
26
|
-
>>> from kailash.mcp.server import SimpleMCPServer
|
27
|
-
>>> server = SimpleMCPServer("my-tools")
|
28
|
-
>>> @server.tool()
|
29
|
-
... def search(query: str) -> list:
|
30
|
-
... return [f"Result for {query}"]
|
31
|
-
>>> server.start()
|
32
|
-
"""
|
33
|
-
|
34
|
-
import logging
|
35
|
-
from abc import ABC, abstractmethod
|
36
|
-
from collections.abc import Callable
|
37
|
-
|
38
|
-
logger = logging.getLogger(__name__)
|
39
|
-
|
40
|
-
|
41
|
-
class MCPServer(ABC):
|
42
|
-
"""Base class for MCP servers using FastMCP.
|
43
|
-
|
44
|
-
This provides a framework for creating MCP servers that expose
|
45
|
-
tools, resources, and prompts via the Model Context Protocol.
|
46
|
-
|
47
|
-
Examples:
|
48
|
-
Creating a custom server:
|
49
|
-
|
50
|
-
>>> class MyServer(MCPServer):
|
51
|
-
... def setup(self):
|
52
|
-
... @self.add_tool()
|
53
|
-
... def search(query: str) -> str:
|
54
|
-
... return f"Results for: {query}"
|
55
|
-
... @self.add_resource("data://example")
|
56
|
-
... def get_example():
|
57
|
-
... return "Example data"
|
58
|
-
>>> server = MyServer("my-server", port=8080)
|
59
|
-
>>> server.start() # Runs until stopped
|
60
|
-
"""
|
61
|
-
|
62
|
-
def __init__(self, name: str, port: int = 8080, host: str = "localhost"):
|
63
|
-
"""Initialize the MCP server.
|
64
|
-
|
65
|
-
Args:
|
66
|
-
name: Name of the server.
|
67
|
-
port: Port to listen on (default: 8080).
|
68
|
-
host: Host to bind to (default: "localhost").
|
69
|
-
"""
|
70
|
-
self.name = name
|
71
|
-
self.port = port
|
72
|
-
self.host = host
|
73
|
-
self._mcp = None
|
74
|
-
self._running = False
|
75
|
-
|
76
|
-
@abstractmethod
|
77
|
-
def setup(self):
|
78
|
-
"""Setup server tools, resources, and prompts.
|
79
|
-
|
80
|
-
This method should be implemented by subclasses to define
|
81
|
-
the server's capabilities using decorators.
|
82
|
-
|
83
|
-
Note:
|
84
|
-
Use @self.add_tool(), @self.add_resource(uri), and
|
85
|
-
@self.add_prompt(name) decorators to register capabilities.
|
86
|
-
"""
|
87
|
-
|
88
|
-
def add_tool(self):
|
89
|
-
"""Decorator to add a tool to the server.
|
90
|
-
|
91
|
-
Returns:
|
92
|
-
Function decorator for registering tools.
|
93
|
-
|
94
|
-
Examples:
|
95
|
-
>>> @server.add_tool()
|
96
|
-
... def calculate(a: int, b: int) -> int:
|
97
|
-
... '''Add two numbers'''
|
98
|
-
... return a + b
|
99
|
-
"""
|
100
|
-
|
101
|
-
def decorator(func: Callable):
|
102
|
-
if self._mcp is None:
|
103
|
-
self._init_mcp()
|
104
|
-
|
105
|
-
# Use FastMCP's tool decorator
|
106
|
-
return self._mcp.tool()(func)
|
107
|
-
|
108
|
-
return decorator
|
109
|
-
|
110
|
-
def add_resource(self, uri: str):
|
111
|
-
"""Decorator to add a resource to the server.
|
112
|
-
|
113
|
-
Args:
|
114
|
-
uri: URI pattern for the resource (supports wildcards).
|
115
|
-
|
116
|
-
Returns:
|
117
|
-
Function decorator for registering resources.
|
118
|
-
|
119
|
-
Examples:
|
120
|
-
>>> @server.add_resource("file:///data/*")
|
121
|
-
... def get_file(path: str) -> str:
|
122
|
-
... return f"Content of {path}"
|
123
|
-
"""
|
124
|
-
|
125
|
-
def decorator(func: Callable):
|
126
|
-
if self._mcp is None:
|
127
|
-
self._init_mcp()
|
128
|
-
|
129
|
-
# Use FastMCP's resource decorator
|
130
|
-
return self._mcp.resource(uri)(func)
|
131
|
-
|
132
|
-
return decorator
|
133
|
-
|
134
|
-
def add_prompt(self, name: str):
|
135
|
-
"""Decorator to add a prompt template to the server.
|
136
|
-
|
137
|
-
Args:
|
138
|
-
name: Name of the prompt.
|
139
|
-
|
140
|
-
Returns:
|
141
|
-
Function decorator for registering prompts.
|
142
|
-
|
143
|
-
Examples:
|
144
|
-
>>> @server.add_prompt("analyze")
|
145
|
-
... def analyze_prompt(data: str) -> str:
|
146
|
-
... return f"Please analyze the following data: {data}"
|
147
|
-
"""
|
148
|
-
|
149
|
-
def decorator(func: Callable):
|
150
|
-
if self._mcp is None:
|
151
|
-
self._init_mcp()
|
152
|
-
|
153
|
-
# Use FastMCP's prompt decorator
|
154
|
-
return self._mcp.prompt(name)(func)
|
155
|
-
|
156
|
-
return decorator
|
157
|
-
|
158
|
-
def _init_mcp(self):
|
159
|
-
"""Initialize the FastMCP instance."""
|
160
|
-
try:
|
161
|
-
from mcp.server.fastmcp import FastMCP
|
162
|
-
|
163
|
-
self._mcp = FastMCP(self.name)
|
164
|
-
except ImportError:
|
165
|
-
logger.error(
|
166
|
-
"FastMCP not available. Install with: pip install 'mcp[server]'"
|
167
|
-
)
|
168
|
-
raise
|
169
|
-
|
170
|
-
def start(self):
|
171
|
-
"""Start the MCP server.
|
172
|
-
|
173
|
-
This runs the server as a long-lived process until stopped.
|
174
|
-
|
175
|
-
Raises:
|
176
|
-
ImportError: If FastMCP is not available.
|
177
|
-
Exception: If server fails to start.
|
178
|
-
"""
|
179
|
-
if self._mcp is None:
|
180
|
-
self._init_mcp()
|
181
|
-
|
182
|
-
# Run setup to register tools/resources
|
183
|
-
self.setup()
|
184
|
-
|
185
|
-
logger.info(f"Starting MCP server '{self.name}' on {self.host}:{self.port}")
|
186
|
-
self._running = True
|
187
|
-
|
188
|
-
try:
|
189
|
-
# Run the FastMCP server
|
190
|
-
logger.info("Running FastMCP server in stdio mode")
|
191
|
-
self._mcp.run()
|
192
|
-
except Exception as e:
|
193
|
-
logger.error(f"Failed to start server: {e}")
|
194
|
-
raise
|
195
|
-
finally:
|
196
|
-
self._running = False
|
197
|
-
|
198
|
-
def stop(self):
|
199
|
-
"""Stop the MCP server."""
|
200
|
-
logger.info(f"Stopping MCP server '{self.name}'")
|
201
|
-
self._running = False
|
202
|
-
# In a real implementation, we'd need to handle graceful shutdown
|
203
|
-
|
204
|
-
|
205
|
-
class SimpleMCPServer(MCPServer):
|
206
|
-
"""Simple MCP server for basic use cases.
|
207
|
-
|
208
|
-
This provides an easy way to create MCP servers without subclassing.
|
209
|
-
|
210
|
-
Examples:
|
211
|
-
>>> server = SimpleMCPServer("my-server")
|
212
|
-
>>> @server.tool()
|
213
|
-
... def add(a: int, b: int) -> int:
|
214
|
-
... return a + b
|
215
|
-
>>> server.start()
|
216
|
-
"""
|
217
|
-
|
218
|
-
def __init__(self, name: str, port: int = 8080, host: str = "localhost"):
|
219
|
-
"""Initialize the simple MCP server.
|
220
|
-
|
221
|
-
Args:
|
222
|
-
name: Name of the server.
|
223
|
-
port: Port to listen on (default: 8080).
|
224
|
-
host: Host to bind to (default: "localhost").
|
225
|
-
"""
|
226
|
-
super().__init__(name, port, host)
|
227
|
-
self._tools = []
|
228
|
-
self._resources = []
|
229
|
-
self._prompts = []
|
230
|
-
|
231
|
-
def tool(self):
|
232
|
-
"""Decorator to add a tool.
|
233
|
-
|
234
|
-
Returns:
|
235
|
-
Function decorator for registering tools.
|
236
|
-
"""
|
237
|
-
|
238
|
-
def decorator(func):
|
239
|
-
self._tools.append(func)
|
240
|
-
return func
|
241
|
-
|
242
|
-
return decorator
|
243
|
-
|
244
|
-
def resource(self, uri: str):
|
245
|
-
"""Decorator to add a resource.
|
246
|
-
|
247
|
-
Args:
|
248
|
-
uri: URI pattern for the resource.
|
249
|
-
|
250
|
-
Returns:
|
251
|
-
Function decorator for registering resources.
|
252
|
-
"""
|
253
|
-
|
254
|
-
def decorator(func):
|
255
|
-
self._resources.append((uri, func))
|
256
|
-
return func
|
257
|
-
|
258
|
-
return decorator
|
259
|
-
|
260
|
-
def prompt(self, name: str):
|
261
|
-
"""Decorator to add a prompt.
|
262
|
-
|
263
|
-
Args:
|
264
|
-
name: Name of the prompt.
|
265
|
-
|
266
|
-
Returns:
|
267
|
-
Function decorator for registering prompts.
|
268
|
-
"""
|
269
|
-
|
270
|
-
def decorator(func):
|
271
|
-
self._prompts.append((name, func))
|
272
|
-
return func
|
273
|
-
|
274
|
-
return decorator
|
275
|
-
|
276
|
-
def setup(self):
|
277
|
-
"""Setup the server with registered components.
|
278
|
-
|
279
|
-
Registers all tools, resources, and prompts that were decorated
|
280
|
-
before calling start().
|
281
|
-
"""
|
282
|
-
# Register all tools
|
283
|
-
for tool_func in self._tools:
|
284
|
-
self.add_tool()(tool_func)
|
285
|
-
|
286
|
-
# Register all resources
|
287
|
-
for uri, resource_func in self._resources:
|
288
|
-
self.add_resource(uri)(resource_func)
|
289
|
-
|
290
|
-
# Register all prompts
|
291
|
-
for name, prompt_func in self._prompts:
|
292
|
-
self.add_prompt(name)(prompt_func)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|