sunholo 0.143.3__py3-none-any.whl → 0.143.7__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.
- sunholo/__init__.py +4 -1
- sunholo/agents/flask/vac_routes.py +9 -17
- sunholo/mcp/__init__.py +11 -2
- sunholo/mcp/mcp_manager.py +66 -28
- sunholo/mcp/vac_mcp_server.py +3 -9
- {sunholo-0.143.3.dist-info → sunholo-0.143.7.dist-info}/METADATA +1 -1
- {sunholo-0.143.3.dist-info → sunholo-0.143.7.dist-info}/RECORD +11 -11
- {sunholo-0.143.3.dist-info → sunholo-0.143.7.dist-info}/WHEEL +0 -0
- {sunholo-0.143.3.dist-info → sunholo-0.143.7.dist-info}/entry_points.txt +0 -0
- {sunholo-0.143.3.dist-info → sunholo-0.143.7.dist-info}/licenses/LICENSE.txt +0 -0
- {sunholo-0.143.3.dist-info → sunholo-0.143.7.dist-info}/top_level.txt +0 -0
sunholo/__init__.py
CHANGED
@@ -15,7 +15,10 @@ from . import invoke
|
|
15
15
|
from . import langfuse
|
16
16
|
from . import llamaindex
|
17
17
|
from . import lookup
|
18
|
-
|
18
|
+
try:
|
19
|
+
from . import mcp
|
20
|
+
except ImportError:
|
21
|
+
mcp = None
|
19
22
|
from . import ollama
|
20
23
|
from . import pubsub
|
21
24
|
from . import qna
|
@@ -38,12 +38,14 @@ except ImportError:
|
|
38
38
|
|
39
39
|
try:
|
40
40
|
from ...mcp.vac_mcp_server import VACMCPServer
|
41
|
-
from mcp.server
|
42
|
-
from mcp import JSONRPCMessage, ErrorData, INTERNAL_ERROR
|
41
|
+
from mcp.server import Server
|
42
|
+
from mcp.types import JSONRPCMessage, ErrorData, INTERNAL_ERROR
|
43
43
|
except ImportError:
|
44
44
|
VACMCPServer = None
|
45
|
-
|
45
|
+
Server = None
|
46
46
|
JSONRPCMessage = None
|
47
|
+
ErrorData = None
|
48
|
+
INTERNAL_ERROR = None
|
47
49
|
|
48
50
|
try:
|
49
51
|
from ...a2a.vac_a2a_agent import VACA2AAgent
|
@@ -1062,11 +1064,8 @@ if __name__ == "__main__":
|
|
1062
1064
|
|
1063
1065
|
try:
|
1064
1066
|
# Process the request through the server
|
1065
|
-
|
1066
|
-
|
1067
|
-
write_queue,
|
1068
|
-
InitializationOptions() if InitializationOptions else None
|
1069
|
-
)
|
1067
|
+
# Use the server's run method with HTTP transport
|
1068
|
+
await server.run()
|
1070
1069
|
except Exception as e:
|
1071
1070
|
log.error(f"Error processing MCP request: {e}")
|
1072
1071
|
await write_queue.put(None)
|
@@ -1084,15 +1083,8 @@ if __name__ == "__main__":
|
|
1084
1083
|
loop = asyncio.new_event_loop()
|
1085
1084
|
asyncio.set_event_loop(loop)
|
1086
1085
|
try:
|
1087
|
-
|
1088
|
-
|
1089
|
-
# Parse and return the response
|
1090
|
-
if responses:
|
1091
|
-
# The response should be a single JSON-RPC response
|
1092
|
-
response_data = json_module.loads(responses[0])
|
1093
|
-
return jsonify(response_data)
|
1094
|
-
else:
|
1095
|
-
return jsonify({"error": "No response from MCP server"}), 500
|
1086
|
+
response_data = loop.run_until_complete(process_request())
|
1087
|
+
return jsonify(response_data)
|
1096
1088
|
|
1097
1089
|
except Exception as e:
|
1098
1090
|
log.error(f"MCP server error: {str(e)}")
|
sunholo/mcp/__init__.py
CHANGED
@@ -14,7 +14,16 @@
|
|
14
14
|
|
15
15
|
"""MCP (Model Context Protocol) integration for Sunholo."""
|
16
16
|
|
17
|
-
|
18
|
-
from .
|
17
|
+
try:
|
18
|
+
from .mcp_manager import MCPClientManager
|
19
|
+
except ImportError as e:
|
20
|
+
print(f"Warning: MCPClientManager not available - {e}")
|
21
|
+
MCPClientManager = None
|
22
|
+
|
23
|
+
try:
|
24
|
+
from .vac_mcp_server import VACMCPServer
|
25
|
+
except ImportError as e:
|
26
|
+
print(f"Warning: VACMCPServer not available - {e}")
|
27
|
+
VACMCPServer = None
|
19
28
|
|
20
29
|
__all__ = ['MCPClientManager', 'VACMCPServer']
|
sunholo/mcp/mcp_manager.py
CHANGED
@@ -4,11 +4,34 @@ This shows how to integrate MCP servers with your Flask/VACRoutes application.
|
|
4
4
|
"""
|
5
5
|
|
6
6
|
from typing import Dict, Any, List, Optional
|
7
|
+
import asyncio
|
7
8
|
|
8
|
-
#
|
9
|
-
|
10
|
-
from mcp.client.stdio import
|
11
|
-
from mcp.
|
9
|
+
# MCP SDK imports - try different import paths
|
10
|
+
try:
|
11
|
+
from mcp.client.stdio import StdioClientTransport
|
12
|
+
from mcp.client.session import ClientSession
|
13
|
+
except ImportError:
|
14
|
+
try:
|
15
|
+
# Alternative import paths
|
16
|
+
from mcp.client import StdioClientTransport, ClientSession
|
17
|
+
except ImportError:
|
18
|
+
try:
|
19
|
+
# Another alternative
|
20
|
+
from mcp import StdioClientTransport, ClientSession
|
21
|
+
except ImportError:
|
22
|
+
StdioClientTransport = None
|
23
|
+
ClientSession = None
|
24
|
+
|
25
|
+
try:
|
26
|
+
from mcp.types import Tool, Resource, TextContent, CallToolResult
|
27
|
+
except ImportError:
|
28
|
+
try:
|
29
|
+
from mcp import Tool, Resource, TextContent, CallToolResult
|
30
|
+
except ImportError:
|
31
|
+
Tool = None
|
32
|
+
Resource = None
|
33
|
+
TextContent = None
|
34
|
+
CallToolResult = None
|
12
35
|
|
13
36
|
|
14
37
|
class MCPClientManager:
|
@@ -23,41 +46,42 @@ class MCPClientManager:
|
|
23
46
|
if server_name in self.sessions:
|
24
47
|
return self.sessions[server_name]
|
25
48
|
|
26
|
-
|
27
|
-
|
49
|
+
if not StdioClientTransport or not ClientSession:
|
50
|
+
raise ImportError("MCP client dependencies not available")
|
51
|
+
|
52
|
+
# Create transport and session
|
53
|
+
transport = StdioClientTransport(
|
28
54
|
command=command,
|
29
55
|
args=args or []
|
30
56
|
)
|
57
|
+
session = ClientSession(transport)
|
58
|
+
await session.initialize()
|
31
59
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
self.server_configs[server_name] = {
|
39
|
-
"command": command,
|
40
|
-
"args": args
|
41
|
-
}
|
42
|
-
return session
|
60
|
+
self.sessions[server_name] = session
|
61
|
+
self.server_configs[server_name] = {
|
62
|
+
"command": command,
|
63
|
+
"args": args
|
64
|
+
}
|
65
|
+
return session
|
43
66
|
|
44
67
|
async def list_tools(self, server_name: Optional[str] = None) -> List[Tool]:
|
45
68
|
"""List available tools from one or all connected servers."""
|
46
69
|
if server_name:
|
47
70
|
session = self.sessions.get(server_name)
|
48
71
|
if session:
|
49
|
-
|
72
|
+
result = await session.list_tools()
|
73
|
+
return result.tools
|
50
74
|
return []
|
51
75
|
|
52
76
|
# List from all servers
|
53
77
|
all_tools = []
|
54
78
|
for name, session in self.sessions.items():
|
55
|
-
|
79
|
+
result = await session.list_tools()
|
56
80
|
# Add server name to tool metadata
|
57
|
-
for tool in tools:
|
81
|
+
for tool in result.tools:
|
58
82
|
tool.metadata = tool.metadata or {}
|
59
83
|
tool.metadata["server"] = name
|
60
|
-
all_tools.extend(tools)
|
84
|
+
all_tools.extend(result.tools)
|
61
85
|
return all_tools
|
62
86
|
|
63
87
|
async def call_tool(self, server_name: str, tool_name: str, arguments: Dict[str, Any]) -> CallToolResult:
|
@@ -67,7 +91,13 @@ class MCPClientManager:
|
|
67
91
|
raise ValueError(f"Not connected to server: {server_name}")
|
68
92
|
|
69
93
|
# Call the tool
|
70
|
-
|
94
|
+
try:
|
95
|
+
from mcp.types import CallToolRequest
|
96
|
+
request = CallToolRequest(name=tool_name, arguments=arguments)
|
97
|
+
result = await session.call_tool(request)
|
98
|
+
except ImportError:
|
99
|
+
# Try direct call if Request types not available
|
100
|
+
result = await session.call_tool(tool_name, arguments)
|
71
101
|
return result
|
72
102
|
|
73
103
|
async def list_resources(self, server_name: Optional[str] = None) -> List[Resource]:
|
@@ -75,17 +105,18 @@ class MCPClientManager:
|
|
75
105
|
if server_name:
|
76
106
|
session = self.sessions.get(server_name)
|
77
107
|
if session:
|
78
|
-
|
108
|
+
result = await session.list_resources()
|
109
|
+
return result.resources
|
79
110
|
return []
|
80
111
|
|
81
112
|
# List from all servers
|
82
113
|
all_resources = []
|
83
114
|
for name, session in self.sessions.items():
|
84
|
-
|
85
|
-
for resource in resources:
|
115
|
+
result = await session.list_resources()
|
116
|
+
for resource in result.resources:
|
86
117
|
resource.metadata = resource.metadata or {}
|
87
118
|
resource.metadata["server"] = name
|
88
|
-
all_resources.extend(resources)
|
119
|
+
all_resources.extend(result.resources)
|
89
120
|
return all_resources
|
90
121
|
|
91
122
|
async def read_resource(self, server_name: str, uri: str) -> List[TextContent]:
|
@@ -94,5 +125,12 @@ class MCPClientManager:
|
|
94
125
|
if not session:
|
95
126
|
raise ValueError(f"Not connected to server: {server_name}")
|
96
127
|
|
97
|
-
|
98
|
-
|
128
|
+
try:
|
129
|
+
from mcp.types import ReadResourceRequest
|
130
|
+
request = ReadResourceRequest(uri=uri)
|
131
|
+
result = await session.read_resource(request)
|
132
|
+
except ImportError:
|
133
|
+
# Try direct call if Request types not available
|
134
|
+
result = await session.read_resource(uri)
|
135
|
+
|
136
|
+
return result.contents if hasattr(result, 'contents') else result
|
sunholo/mcp/vac_mcp_server.py
CHANGED
@@ -22,13 +22,8 @@ import json
|
|
22
22
|
import asyncio
|
23
23
|
from functools import partial
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
|
28
|
-
except ImportError:
|
29
|
-
Server = None
|
30
|
-
Tool = None
|
31
|
-
TextContent = None
|
25
|
+
from mcp.server import Server
|
26
|
+
from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
|
32
27
|
|
33
28
|
from ..custom_logging import log
|
34
29
|
from ..streaming import start_streaming_chat_async
|
@@ -45,8 +40,7 @@ class VACMCPServer:
|
|
45
40
|
stream_interpreter: The streaming interpreter function
|
46
41
|
vac_interpreter: The static VAC interpreter function (optional)
|
47
42
|
"""
|
48
|
-
|
49
|
-
raise ImportError("MCP server requires `pip install sunholo[anthropic]`")
|
43
|
+
# MCP server is always available with current SDK
|
50
44
|
|
51
45
|
self.stream_interpreter = stream_interpreter
|
52
46
|
self.vac_interpreter = vac_interpreter
|
@@ -1,4 +1,4 @@
|
|
1
|
-
sunholo/__init__.py,sha256=
|
1
|
+
sunholo/__init__.py,sha256=_zHD01JyUVc-kGqm_bWtWxytec3b8-25fm5vK5j_2VU,1256
|
2
2
|
sunholo/custom_logging.py,sha256=JXZTnXp_DixP3jwYfKw4LYRDS9IuTq7ctCgfZbI2rxA,22023
|
3
3
|
sunholo/langchain_types.py,sha256=uZ4zvgej_f7pLqjtu4YP7qMC_eZD5ym_5x4pyvA1Ih4,1834
|
4
4
|
sunholo/a2a/__init__.py,sha256=ohwR-3_toRUdyj3ACNCVPrd_V2lzR5tmL5Hwn1ChSSU,1049
|
@@ -18,7 +18,7 @@ sunholo/agents/fastapi/base.py,sha256=W-cyF8ZDUH40rc-c-Apw3-_8IIi2e4Y9qRtnoVnsc1
|
|
18
18
|
sunholo/agents/fastapi/qna_routes.py,sha256=lKHkXPmwltu9EH3RMwmD153-J6pE7kWQ4BhBlV3to-s,3864
|
19
19
|
sunholo/agents/flask/__init__.py,sha256=dEoByI3gDNUOjpX1uVKP7uPjhfFHJubbiaAv3xLopnk,63
|
20
20
|
sunholo/agents/flask/base.py,sha256=vnpxFEOnCmt9humqj-jYPLfJcdwzsop9NorgkJ-tSaU,1756
|
21
|
-
sunholo/agents/flask/vac_routes.py,sha256=
|
21
|
+
sunholo/agents/flask/vac_routes.py,sha256=MvEsIWxrdeuRx-t_RfkodnJyJKP40aKaADWV4Yi3ijw,53375
|
22
22
|
sunholo/archive/__init__.py,sha256=qNHWm5rGPVOlxZBZCpA1wTYPbalizRT7f8X4rs2t290,31
|
23
23
|
sunholo/archive/archive.py,sha256=PxVfDtO2_2ZEEbnhXSCbXLdeoHoQVImo4y3Jr2XkCFY,1204
|
24
24
|
sunholo/auth/__init__.py,sha256=TeP-OY0XGxYV_8AQcVGoh35bvyWhNUcMRfhuD5l44Sk,91
|
@@ -114,10 +114,10 @@ sunholo/llamaindex/llamaindex_class.py,sha256=PnpPoc7LpP7xvKIXYu-UvI4ehj67pGhE1E
|
|
114
114
|
sunholo/llamaindex/user_history.py,sha256=ZtkecWuF9ORduyGB8kF8gP66bm9DdvCI-ZiK6Kt-cSE,2265
|
115
115
|
sunholo/lookup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
116
116
|
sunholo/lookup/model_lookup.yaml,sha256=O7o-jP53MLA06C8pI-ILwERShO-xf6z_258wtpZBv6A,739
|
117
|
-
sunholo/mcp/__init__.py,sha256=
|
117
|
+
sunholo/mcp/__init__.py,sha256=Bi0ZYMvWuf1AL_QSrMAREVVdTZFiIokGwrytBXKBJyc,1028
|
118
118
|
sunholo/mcp/cli.py,sha256=d24nnVzhZYz4AWgTqmN-qjKG4rPbf8RhdmEOHZkBHy8,10570
|
119
|
-
sunholo/mcp/mcp_manager.py,sha256=
|
120
|
-
sunholo/mcp/vac_mcp_server.py,sha256=
|
119
|
+
sunholo/mcp/mcp_manager.py,sha256=g75vv6XvM24U7uz366slE-p76Qs4AvVcsarHSF9qIvE,5061
|
120
|
+
sunholo/mcp/vac_mcp_server.py,sha256=DSSMsTeLU_1C2hHTvgLjZsg1chyMfb_S9ruCUw2f_dc,9969
|
121
121
|
sunholo/ollama/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
122
122
|
sunholo/ollama/ollama_images.py,sha256=H2cpcNu88R4TwyfL_nnqkQhdvBQ2FPCAy4Ok__0yQmo,2351
|
123
123
|
sunholo/pubsub/__init__.py,sha256=DfTEk4zmCfqn6gFxRrqDO0pOrvXTDqH-medpgYO4PGw,117
|
@@ -175,9 +175,9 @@ sunholo/vertex/init.py,sha256=1OQwcPBKZYBTDPdyU7IM4X4OmiXLdsNV30C-fee2scQ,2875
|
|
175
175
|
sunholo/vertex/memory_tools.py,sha256=tBZxqVZ4InTmdBvLlOYwoSEWu4-kGquc-gxDwZCC4FA,7667
|
176
176
|
sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
|
177
177
|
sunholo/vertex/type_dict_to_json.py,sha256=uTzL4o9tJRao4u-gJOFcACgWGkBOtqACmb6ihvCErL8,4694
|
178
|
-
sunholo-0.143.
|
179
|
-
sunholo-0.143.
|
180
|
-
sunholo-0.143.
|
181
|
-
sunholo-0.143.
|
182
|
-
sunholo-0.143.
|
183
|
-
sunholo-0.143.
|
178
|
+
sunholo-0.143.7.dist-info/licenses/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
179
|
+
sunholo-0.143.7.dist-info/METADATA,sha256=c1IhnVsC3r20UUvBImOmvOIirVrkuNY6Tj-xFuF3jr0,18413
|
180
|
+
sunholo-0.143.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
181
|
+
sunholo-0.143.7.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
182
|
+
sunholo-0.143.7.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
183
|
+
sunholo-0.143.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|