massgen 0.0.3__py3-none-any.whl → 0.1.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.

Potentially problematic release.


This version of massgen might be problematic. Click here for more details.

Files changed (268) hide show
  1. massgen/__init__.py +142 -8
  2. massgen/adapters/__init__.py +29 -0
  3. massgen/adapters/ag2_adapter.py +483 -0
  4. massgen/adapters/base.py +183 -0
  5. massgen/adapters/tests/__init__.py +0 -0
  6. massgen/adapters/tests/test_ag2_adapter.py +439 -0
  7. massgen/adapters/tests/test_agent_adapter.py +128 -0
  8. massgen/adapters/utils/__init__.py +2 -0
  9. massgen/adapters/utils/ag2_utils.py +236 -0
  10. massgen/adapters/utils/tests/__init__.py +0 -0
  11. massgen/adapters/utils/tests/test_ag2_utils.py +138 -0
  12. massgen/agent_config.py +329 -55
  13. massgen/api_params_handler/__init__.py +10 -0
  14. massgen/api_params_handler/_api_params_handler_base.py +99 -0
  15. massgen/api_params_handler/_chat_completions_api_params_handler.py +176 -0
  16. massgen/api_params_handler/_claude_api_params_handler.py +113 -0
  17. massgen/api_params_handler/_response_api_params_handler.py +130 -0
  18. massgen/backend/__init__.py +39 -4
  19. massgen/backend/azure_openai.py +385 -0
  20. massgen/backend/base.py +341 -69
  21. massgen/backend/base_with_mcp.py +1102 -0
  22. massgen/backend/capabilities.py +386 -0
  23. massgen/backend/chat_completions.py +577 -130
  24. massgen/backend/claude.py +1033 -537
  25. massgen/backend/claude_code.py +1203 -0
  26. massgen/backend/cli_base.py +209 -0
  27. massgen/backend/docs/BACKEND_ARCHITECTURE.md +126 -0
  28. massgen/backend/{CLAUDE_API_RESEARCH.md → docs/CLAUDE_API_RESEARCH.md} +18 -18
  29. massgen/backend/{GEMINI_API_DOCUMENTATION.md → docs/GEMINI_API_DOCUMENTATION.md} +9 -9
  30. massgen/backend/docs/Gemini MCP Integration Analysis.md +1050 -0
  31. massgen/backend/docs/MCP_IMPLEMENTATION_CLAUDE_BACKEND.md +177 -0
  32. massgen/backend/docs/MCP_INTEGRATION_RESPONSE_BACKEND.md +352 -0
  33. massgen/backend/docs/OPENAI_GPT5_MODELS.md +211 -0
  34. massgen/backend/{OPENAI_RESPONSES_API_FORMAT.md → docs/OPENAI_RESPONSE_API_TOOL_CALLS.md} +3 -3
  35. massgen/backend/docs/OPENAI_response_streaming.md +20654 -0
  36. massgen/backend/docs/inference_backend.md +257 -0
  37. massgen/backend/docs/permissions_and_context_files.md +1085 -0
  38. massgen/backend/external.py +126 -0
  39. massgen/backend/gemini.py +1850 -241
  40. massgen/backend/grok.py +40 -156
  41. massgen/backend/inference.py +156 -0
  42. massgen/backend/lmstudio.py +171 -0
  43. massgen/backend/response.py +1095 -322
  44. massgen/chat_agent.py +131 -113
  45. massgen/cli.py +1560 -275
  46. massgen/config_builder.py +2396 -0
  47. massgen/configs/BACKEND_CONFIGURATION.md +458 -0
  48. massgen/configs/README.md +559 -216
  49. massgen/configs/ag2/ag2_case_study.yaml +27 -0
  50. massgen/configs/ag2/ag2_coder.yaml +34 -0
  51. massgen/configs/ag2/ag2_coder_case_study.yaml +36 -0
  52. massgen/configs/ag2/ag2_gemini.yaml +27 -0
  53. massgen/configs/ag2/ag2_groupchat.yaml +108 -0
  54. massgen/configs/ag2/ag2_groupchat_gpt.yaml +118 -0
  55. massgen/configs/ag2/ag2_single_agent.yaml +21 -0
  56. massgen/configs/basic/multi/fast_timeout_example.yaml +37 -0
  57. massgen/configs/basic/multi/gemini_4o_claude.yaml +31 -0
  58. massgen/configs/basic/multi/gemini_gpt5nano_claude.yaml +36 -0
  59. massgen/configs/{gemini_4o_claude.yaml → basic/multi/geminicode_4o_claude.yaml} +3 -3
  60. massgen/configs/basic/multi/geminicode_gpt5nano_claude.yaml +36 -0
  61. massgen/configs/basic/multi/glm_gemini_claude.yaml +25 -0
  62. massgen/configs/basic/multi/gpt4o_audio_generation.yaml +30 -0
  63. massgen/configs/basic/multi/gpt4o_image_generation.yaml +31 -0
  64. massgen/configs/basic/multi/gpt5nano_glm_qwen.yaml +26 -0
  65. massgen/configs/basic/multi/gpt5nano_image_understanding.yaml +26 -0
  66. massgen/configs/{three_agents_default.yaml → basic/multi/three_agents_default.yaml} +8 -4
  67. massgen/configs/basic/multi/three_agents_opensource.yaml +27 -0
  68. massgen/configs/basic/multi/three_agents_vllm.yaml +20 -0
  69. massgen/configs/basic/multi/two_agents_gemini.yaml +19 -0
  70. massgen/configs/{two_agents.yaml → basic/multi/two_agents_gpt5.yaml} +14 -6
  71. massgen/configs/basic/multi/two_agents_opensource_lmstudio.yaml +31 -0
  72. massgen/configs/basic/multi/two_qwen_vllm_sglang.yaml +28 -0
  73. massgen/configs/{single_agent.yaml → basic/single/single_agent.yaml} +1 -1
  74. massgen/configs/{single_flash2.5.yaml → basic/single/single_flash2.5.yaml} +1 -2
  75. massgen/configs/basic/single/single_gemini2.5pro.yaml +16 -0
  76. massgen/configs/basic/single/single_gpt4o_audio_generation.yaml +22 -0
  77. massgen/configs/basic/single/single_gpt4o_image_generation.yaml +22 -0
  78. massgen/configs/basic/single/single_gpt4o_video_generation.yaml +24 -0
  79. massgen/configs/basic/single/single_gpt5nano.yaml +20 -0
  80. massgen/configs/basic/single/single_gpt5nano_file_search.yaml +18 -0
  81. massgen/configs/basic/single/single_gpt5nano_image_understanding.yaml +17 -0
  82. massgen/configs/basic/single/single_gptoss120b.yaml +15 -0
  83. massgen/configs/basic/single/single_openrouter_audio_understanding.yaml +15 -0
  84. massgen/configs/basic/single/single_qwen_video_understanding.yaml +15 -0
  85. massgen/configs/debug/code_execution/command_filtering_blacklist.yaml +29 -0
  86. massgen/configs/debug/code_execution/command_filtering_whitelist.yaml +28 -0
  87. massgen/configs/debug/code_execution/docker_verification.yaml +29 -0
  88. massgen/configs/debug/skip_coordination_test.yaml +27 -0
  89. massgen/configs/debug/test_sdk_migration.yaml +17 -0
  90. massgen/configs/docs/DISCORD_MCP_SETUP.md +208 -0
  91. massgen/configs/docs/TWITTER_MCP_ENESCINAR_SETUP.md +82 -0
  92. massgen/configs/providers/azure/azure_openai_multi.yaml +21 -0
  93. massgen/configs/providers/azure/azure_openai_single.yaml +19 -0
  94. massgen/configs/providers/claude/claude.yaml +14 -0
  95. massgen/configs/providers/gemini/gemini_gpt5nano.yaml +28 -0
  96. massgen/configs/providers/local/lmstudio.yaml +11 -0
  97. massgen/configs/providers/openai/gpt5.yaml +46 -0
  98. massgen/configs/providers/openai/gpt5_nano.yaml +46 -0
  99. massgen/configs/providers/others/grok_single_agent.yaml +19 -0
  100. massgen/configs/providers/others/zai_coding_team.yaml +108 -0
  101. massgen/configs/providers/others/zai_glm45.yaml +12 -0
  102. massgen/configs/{creative_team.yaml → teams/creative/creative_team.yaml} +16 -6
  103. massgen/configs/{travel_planning.yaml → teams/creative/travel_planning.yaml} +16 -6
  104. massgen/configs/{news_analysis.yaml → teams/research/news_analysis.yaml} +16 -6
  105. massgen/configs/{research_team.yaml → teams/research/research_team.yaml} +15 -7
  106. massgen/configs/{technical_analysis.yaml → teams/research/technical_analysis.yaml} +16 -6
  107. massgen/configs/tools/code-execution/basic_command_execution.yaml +25 -0
  108. massgen/configs/tools/code-execution/code_execution_use_case_simple.yaml +41 -0
  109. massgen/configs/tools/code-execution/docker_claude_code.yaml +32 -0
  110. massgen/configs/tools/code-execution/docker_multi_agent.yaml +32 -0
  111. massgen/configs/tools/code-execution/docker_simple.yaml +29 -0
  112. massgen/configs/tools/code-execution/docker_with_resource_limits.yaml +32 -0
  113. massgen/configs/tools/code-execution/multi_agent_playwright_automation.yaml +57 -0
  114. massgen/configs/tools/filesystem/cc_gpt5_gemini_filesystem.yaml +34 -0
  115. massgen/configs/tools/filesystem/claude_code_context_sharing.yaml +68 -0
  116. massgen/configs/tools/filesystem/claude_code_flash2.5.yaml +43 -0
  117. massgen/configs/tools/filesystem/claude_code_flash2.5_gptoss.yaml +49 -0
  118. massgen/configs/tools/filesystem/claude_code_gpt5nano.yaml +31 -0
  119. massgen/configs/tools/filesystem/claude_code_single.yaml +40 -0
  120. massgen/configs/tools/filesystem/fs_permissions_test.yaml +87 -0
  121. massgen/configs/tools/filesystem/gemini_gemini_workspace_cleanup.yaml +54 -0
  122. massgen/configs/tools/filesystem/gemini_gpt5_filesystem_casestudy.yaml +30 -0
  123. massgen/configs/tools/filesystem/gemini_gpt5nano_file_context_path.yaml +43 -0
  124. massgen/configs/tools/filesystem/gemini_gpt5nano_protected_paths.yaml +45 -0
  125. massgen/configs/tools/filesystem/gpt5mini_cc_fs_context_path.yaml +31 -0
  126. massgen/configs/tools/filesystem/grok4_gpt5_gemini_filesystem.yaml +32 -0
  127. massgen/configs/tools/filesystem/multiturn/grok4_gpt5_claude_code_filesystem_multiturn.yaml +58 -0
  128. massgen/configs/tools/filesystem/multiturn/grok4_gpt5_gemini_filesystem_multiturn.yaml +58 -0
  129. massgen/configs/tools/filesystem/multiturn/two_claude_code_filesystem_multiturn.yaml +47 -0
  130. massgen/configs/tools/filesystem/multiturn/two_gemini_flash_filesystem_multiturn.yaml +48 -0
  131. massgen/configs/tools/mcp/claude_code_discord_mcp_example.yaml +27 -0
  132. massgen/configs/tools/mcp/claude_code_simple_mcp.yaml +35 -0
  133. massgen/configs/tools/mcp/claude_code_twitter_mcp_example.yaml +32 -0
  134. massgen/configs/tools/mcp/claude_mcp_example.yaml +24 -0
  135. massgen/configs/tools/mcp/claude_mcp_test.yaml +27 -0
  136. massgen/configs/tools/mcp/five_agents_travel_mcp_test.yaml +157 -0
  137. massgen/configs/tools/mcp/five_agents_weather_mcp_test.yaml +103 -0
  138. massgen/configs/tools/mcp/gemini_mcp_example.yaml +24 -0
  139. massgen/configs/tools/mcp/gemini_mcp_filesystem_test.yaml +23 -0
  140. massgen/configs/tools/mcp/gemini_mcp_filesystem_test_sharing.yaml +23 -0
  141. massgen/configs/tools/mcp/gemini_mcp_filesystem_test_single_agent.yaml +17 -0
  142. massgen/configs/tools/mcp/gemini_mcp_filesystem_test_with_claude_code.yaml +24 -0
  143. massgen/configs/tools/mcp/gemini_mcp_test.yaml +27 -0
  144. massgen/configs/tools/mcp/gemini_notion_mcp.yaml +52 -0
  145. massgen/configs/tools/mcp/gpt5_nano_mcp_example.yaml +24 -0
  146. massgen/configs/tools/mcp/gpt5_nano_mcp_test.yaml +27 -0
  147. massgen/configs/tools/mcp/gpt5mini_claude_code_discord_mcp_example.yaml +38 -0
  148. massgen/configs/tools/mcp/gpt_oss_mcp_example.yaml +25 -0
  149. massgen/configs/tools/mcp/gpt_oss_mcp_test.yaml +28 -0
  150. massgen/configs/tools/mcp/grok3_mini_mcp_example.yaml +24 -0
  151. massgen/configs/tools/mcp/grok3_mini_mcp_test.yaml +27 -0
  152. massgen/configs/tools/mcp/multimcp_gemini.yaml +111 -0
  153. massgen/configs/tools/mcp/qwen_api_mcp_example.yaml +25 -0
  154. massgen/configs/tools/mcp/qwen_api_mcp_test.yaml +28 -0
  155. massgen/configs/tools/mcp/qwen_local_mcp_example.yaml +24 -0
  156. massgen/configs/tools/mcp/qwen_local_mcp_test.yaml +27 -0
  157. massgen/configs/tools/planning/five_agents_discord_mcp_planning_mode.yaml +140 -0
  158. massgen/configs/tools/planning/five_agents_filesystem_mcp_planning_mode.yaml +151 -0
  159. massgen/configs/tools/planning/five_agents_notion_mcp_planning_mode.yaml +151 -0
  160. massgen/configs/tools/planning/five_agents_twitter_mcp_planning_mode.yaml +155 -0
  161. massgen/configs/tools/planning/gpt5_mini_case_study_mcp_planning_mode.yaml +73 -0
  162. massgen/configs/tools/web-search/claude_streamable_http_test.yaml +43 -0
  163. massgen/configs/tools/web-search/gemini_streamable_http_test.yaml +43 -0
  164. massgen/configs/tools/web-search/gpt5_mini_streamable_http_test.yaml +43 -0
  165. massgen/configs/tools/web-search/gpt_oss_streamable_http_test.yaml +44 -0
  166. massgen/configs/tools/web-search/grok3_mini_streamable_http_test.yaml +43 -0
  167. massgen/configs/tools/web-search/qwen_api_streamable_http_test.yaml +44 -0
  168. massgen/configs/tools/web-search/qwen_local_streamable_http_test.yaml +43 -0
  169. massgen/coordination_tracker.py +708 -0
  170. massgen/docker/README.md +462 -0
  171. massgen/filesystem_manager/__init__.py +21 -0
  172. massgen/filesystem_manager/_base.py +9 -0
  173. massgen/filesystem_manager/_code_execution_server.py +545 -0
  174. massgen/filesystem_manager/_docker_manager.py +477 -0
  175. massgen/filesystem_manager/_file_operation_tracker.py +248 -0
  176. massgen/filesystem_manager/_filesystem_manager.py +813 -0
  177. massgen/filesystem_manager/_path_permission_manager.py +1261 -0
  178. massgen/filesystem_manager/_workspace_tools_server.py +1815 -0
  179. massgen/formatter/__init__.py +10 -0
  180. massgen/formatter/_chat_completions_formatter.py +284 -0
  181. massgen/formatter/_claude_formatter.py +235 -0
  182. massgen/formatter/_formatter_base.py +156 -0
  183. massgen/formatter/_response_formatter.py +263 -0
  184. massgen/frontend/__init__.py +1 -2
  185. massgen/frontend/coordination_ui.py +471 -286
  186. massgen/frontend/displays/base_display.py +56 -11
  187. massgen/frontend/displays/create_coordination_table.py +1956 -0
  188. massgen/frontend/displays/rich_terminal_display.py +1259 -619
  189. massgen/frontend/displays/simple_display.py +9 -4
  190. massgen/frontend/displays/terminal_display.py +27 -68
  191. massgen/logger_config.py +681 -0
  192. massgen/mcp_tools/README.md +232 -0
  193. massgen/mcp_tools/__init__.py +105 -0
  194. massgen/mcp_tools/backend_utils.py +1035 -0
  195. massgen/mcp_tools/circuit_breaker.py +195 -0
  196. massgen/mcp_tools/client.py +894 -0
  197. massgen/mcp_tools/config_validator.py +138 -0
  198. massgen/mcp_tools/docs/circuit_breaker.md +646 -0
  199. massgen/mcp_tools/docs/client.md +950 -0
  200. massgen/mcp_tools/docs/config_validator.md +478 -0
  201. massgen/mcp_tools/docs/exceptions.md +1165 -0
  202. massgen/mcp_tools/docs/security.md +854 -0
  203. massgen/mcp_tools/exceptions.py +338 -0
  204. massgen/mcp_tools/hooks.py +212 -0
  205. massgen/mcp_tools/security.py +780 -0
  206. massgen/message_templates.py +342 -64
  207. massgen/orchestrator.py +1515 -241
  208. massgen/stream_chunk/__init__.py +35 -0
  209. massgen/stream_chunk/base.py +92 -0
  210. massgen/stream_chunk/multimodal.py +237 -0
  211. massgen/stream_chunk/text.py +162 -0
  212. massgen/tests/mcp_test_server.py +150 -0
  213. massgen/tests/multi_turn_conversation_design.md +0 -8
  214. massgen/tests/test_azure_openai_backend.py +156 -0
  215. massgen/tests/test_backend_capabilities.py +262 -0
  216. massgen/tests/test_backend_event_loop_all.py +179 -0
  217. massgen/tests/test_chat_completions_refactor.py +142 -0
  218. massgen/tests/test_claude_backend.py +15 -28
  219. massgen/tests/test_claude_code.py +268 -0
  220. massgen/tests/test_claude_code_context_sharing.py +233 -0
  221. massgen/tests/test_claude_code_orchestrator.py +175 -0
  222. massgen/tests/test_cli_backends.py +180 -0
  223. massgen/tests/test_code_execution.py +679 -0
  224. massgen/tests/test_external_agent_backend.py +134 -0
  225. massgen/tests/test_final_presentation_fallback.py +237 -0
  226. massgen/tests/test_gemini_planning_mode.py +351 -0
  227. massgen/tests/test_grok_backend.py +7 -10
  228. massgen/tests/test_http_mcp_server.py +42 -0
  229. massgen/tests/test_integration_simple.py +198 -0
  230. massgen/tests/test_mcp_blocking.py +125 -0
  231. massgen/tests/test_message_context_building.py +29 -47
  232. massgen/tests/test_orchestrator_final_presentation.py +48 -0
  233. massgen/tests/test_path_permission_manager.py +2087 -0
  234. massgen/tests/test_rich_terminal_display.py +14 -13
  235. massgen/tests/test_timeout.py +133 -0
  236. massgen/tests/test_v3_3agents.py +11 -12
  237. massgen/tests/test_v3_simple.py +8 -13
  238. massgen/tests/test_v3_three_agents.py +11 -18
  239. massgen/tests/test_v3_two_agents.py +8 -13
  240. massgen/token_manager/__init__.py +7 -0
  241. massgen/token_manager/token_manager.py +400 -0
  242. massgen/utils.py +52 -16
  243. massgen/v1/agent.py +45 -91
  244. massgen/v1/agents.py +18 -53
  245. massgen/v1/backends/gemini.py +50 -153
  246. massgen/v1/backends/grok.py +21 -54
  247. massgen/v1/backends/oai.py +39 -111
  248. massgen/v1/cli.py +36 -93
  249. massgen/v1/config.py +8 -12
  250. massgen/v1/logging.py +43 -127
  251. massgen/v1/main.py +18 -32
  252. massgen/v1/orchestrator.py +68 -209
  253. massgen/v1/streaming_display.py +62 -163
  254. massgen/v1/tools.py +8 -12
  255. massgen/v1/types.py +9 -23
  256. massgen/v1/utils.py +5 -23
  257. massgen-0.1.0.dist-info/METADATA +1245 -0
  258. massgen-0.1.0.dist-info/RECORD +273 -0
  259. massgen-0.1.0.dist-info/entry_points.txt +2 -0
  260. massgen/frontend/logging/__init__.py +0 -9
  261. massgen/frontend/logging/realtime_logger.py +0 -197
  262. massgen-0.0.3.dist-info/METADATA +0 -568
  263. massgen-0.0.3.dist-info/RECORD +0 -76
  264. massgen-0.0.3.dist-info/entry_points.txt +0 -2
  265. /massgen/backend/{Function calling openai responses.md → docs/Function calling openai responses.md} +0 -0
  266. {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/WHEEL +0 -0
  267. {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/licenses/LICENSE +0 -0
  268. {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,950 @@
1
+ # MCP Client Documentation
2
+
3
+ ## Overview
4
+
5
+ The MCP client module provides the core functionality for connecting to and interacting with MCP (Model Context Protocol) servers. It includes two main classes: `MCPClient` for single-server connections and `MultiMCPClient` for managing multiple servers simultaneously.
6
+
7
+ ## Client Architecture
8
+
9
+ The client architecture follows an async-first design with comprehensive error handling and security validation:
10
+
11
+ - **Connection Lifecycle**: Automatic connection management with reconnection capabilities
12
+ - **Security Integration**: Built-in validation using the security module
13
+ - **Circuit Breaker**: Automatic failure detection and recovery
14
+ - **Resource Management**: Proper cleanup and connection pooling
15
+
16
+ ## MCPClient Class
17
+
18
+ The `MCPClient` class handles connections to individual MCP servers and provides methods for tool execution, resource access, and server management.
19
+
20
+ ### Initialization
21
+
22
+ ```python
23
+ from massgen.mcp_tools import MCPClient
24
+
25
+ # Basic configuration
26
+ config = {
27
+ "name": "test_server",
28
+ "type": "stdio",
29
+ "command": "python",
30
+ "args": ["-m", "massgen.tests.mcp_test_server"],
31
+ "security": {
32
+ "level": "moderate"
33
+ },
34
+ "timeout": 30,
35
+ "max_retries": 3
36
+ }
37
+
38
+ client = MCPClient(config)
39
+ ```
40
+
41
+ ### Connection Management
42
+
43
+ #### connect()
44
+
45
+ **What it does**: This function establishes a connection to an MCP server. Think of it like dialing a phone number - it sets up the communication channel so you can start using the server's tools.
46
+
47
+ **Why you need it**: Before you can use any tools from an MCP server, you need to connect to it first. This function handles all the technical details of establishing that connection.
48
+
49
+ **What happens when you call it**:
50
+
51
+ 1. Validates your configuration for security
52
+ 2. Starts the MCP server process (for stdio) or connects to the web server (for HTTP)
53
+ 3. Performs a "handshake" to establish communication
54
+ 4. Discovers what tools, resources, and prompts are available
55
+ 5. Sets up the connection for use
56
+
57
+ ```python
58
+ async def connect_example():
59
+ config = {
60
+ "name": "my_server",
61
+ "type": "stdio",
62
+ "command": "python",
63
+ "args": ["-m", "my_mcp_server"]
64
+ }
65
+
66
+ # Method 1: Using async context manager (recommended)
67
+ # The async context manager connects automatically
68
+ async with MCPClient(config) as client:
69
+ print("✅ Connected successfully!")
70
+
71
+ # Use the client here...
72
+ tools = client.get_available_tools()
73
+ print(f"Available tools: {tools}")
74
+
75
+ # Connection automatically closed when exiting the 'with' block
76
+
77
+ # Method 2: Manual connection management
78
+ client = MCPClient(config)
79
+ try:
80
+ await client.connect()
81
+ print("✅ Connected successfully!")
82
+
83
+ # Use the client...
84
+
85
+ finally:
86
+ await client.disconnect() # Always disconnect when done
87
+ ```
88
+
89
+ #### disconnect()
90
+
91
+ **What it does**: Safely closes the connection to the MCP server. Like hanging up a phone call, it properly ends the communication and cleans up resources.
92
+
93
+ **Why you need it**: Always disconnect when you're done to free up system resources and ensure the server process is properly terminated.
94
+
95
+ **What happens when you call it**:
96
+
97
+ 1. Signals the server that you're disconnecting
98
+ 2. Closes the communication channel
99
+ 3. Terminates the server process (for stdio servers)
100
+ 4. Cleans up memory and file handles
101
+ 5. Resets the client state
102
+
103
+ ```python
104
+ async def manual_connection():
105
+ client = MCPClient(config)
106
+ try:
107
+ await client.connect()
108
+ print("✅ Connected to server")
109
+
110
+ # Do your work here...
111
+ result = await client.call_tool("some_tool", {})
112
+
113
+ except Exception as e:
114
+ print(f"❌ Error occurred: {e}")
115
+ finally:
116
+ # ALWAYS disconnect, even if errors occurred
117
+ await client.disconnect()
118
+ print("✅ Disconnected safely")
119
+
120
+ # ✅ Better approach - use context manager (auto-disconnect)
121
+ async def recommended_approach():
122
+ # The async context manager connects automatically
123
+ async with MCPClient(config) as client:
124
+ # Work with client...
125
+ # Automatic disconnect happens here, even if errors occur
126
+ ```
127
+
128
+ #### reconnect()
129
+
130
+ **What it does**: If the connection to the MCP server is lost or broken, this function tries to reconnect automatically. It's smart about retrying - it waits longer between each attempt to avoid overwhelming a struggling server.
131
+
132
+ **Why you need it**: Network connections can fail, servers can crash, or temporary issues can break the connection. Instead of giving up, this function tries to restore the connection.
133
+
134
+ **Parameters**:
135
+
136
+ - `max_retries`: How many times to try reconnecting (default: 3)
137
+ - `retry_delay`: How long to wait between attempts in seconds (default: 1.0)
138
+
139
+ **Returns**: True if reconnection succeeded, False if all attempts failed
140
+
141
+ ```python
142
+ async def reconnect_example():
143
+ # The async context manager connects automatically
144
+ async with MCPClient(config) as client:
145
+ print("✅ Initial connection established")
146
+
147
+ # Simulate using the client
148
+ try:
149
+ result = await client.call_tool("some_tool", {})
150
+ print(f"Tool result: {result}")
151
+
152
+ except MCPConnectionError as e:
153
+ print(f"❌ Connection lost: {e}")
154
+
155
+ # Try to reconnect
156
+ print("🔄 Attempting to reconnect...")
157
+ success = await client.reconnect(max_retries=5, retry_delay=2.0)
158
+
159
+ if success:
160
+ print("✅ Reconnected successfully!")
161
+ # Try the tool again
162
+ result = await client.call_tool("some_tool", {})
163
+ print(f"Tool result after reconnect: {result}")
164
+ else:
165
+ print("❌ Failed to reconnect after 5 attempts")
166
+
167
+ # ✅ Automatic reconnection with health checks
168
+ async def robust_client_usage():
169
+ # The async context manager connects automatically
170
+ async with MCPClient(config) as client:
171
+
172
+ # Check if connection is healthy before important operations
173
+ if not await client.health_check():
174
+ print("⚠️ Connection seems unhealthy, attempting reconnect...")
175
+ await client.reconnect()
176
+
177
+ # Now proceed with confidence
178
+ result = await client.call_tool("important_tool", {"data": "value"})
179
+ ```
180
+
181
+ ### Tool Operations
182
+
183
+ #### call_tool()
184
+
185
+ **What it does**: This is the main function you'll use to actually run tools on the MCP server. It's like calling a function on a remote computer - you provide the tool name and arguments, and get back the result.
186
+
187
+ **Why you need it**: This is how you actually use the MCP server's capabilities. Whether you want to read files, process data, or perform any other task, you do it through this function.
188
+
189
+ **Parameters**:
190
+
191
+ - `tool_name` (required): The name of the tool you want to run (e.g., "read_file")
192
+ - `arguments` (required): Dictionary of parameters the tool needs (e.g., {"path": "file.txt"})
193
+
194
+ **Returns**: The result from the tool (could be text, data, or complex objects)
195
+
196
+ **What happens when you call it**:
197
+
198
+ 1. Validates that the tool exists on the server
199
+ 2. Checks that your arguments are safe and valid
200
+ 3. Sends the request to the MCP server
201
+ 4. Waits for the server to process it
202
+ 5. Returns the result or raises an error if something went wrong
203
+
204
+ ```python
205
+ async def tool_execution():
206
+ # The async context manager connects automatically
207
+ async with MCPClient(config) as client:
208
+
209
+ # ✅ Simple tool call - like calling a function
210
+ result = await client.call_tool("echo", {"message": "Hello World"})
211
+ print(f"Echo result: {result}")
212
+ # Output: "Hello World" (or whatever the echo tool returns)
213
+
214
+ # ✅ Tool call with multiple arguments
215
+ file_result = await client.call_tool("read_file", {
216
+ "path": "/safe/path/document.txt",
217
+ "encoding": "utf-8",
218
+ "max_lines": 100
219
+ })
220
+ print(f"File contents: {file_result}")
221
+
222
+ # ✅ Tool call with complex data
223
+ analysis_result = await client.call_tool("analyze_data", {
224
+ "data": [1, 2, 3, 4, 5],
225
+ "options": {
226
+ "method": "statistical",
227
+ "include_graphs": True
228
+ }
229
+ })
230
+ print(f"Analysis: {analysis_result}")
231
+
232
+ # ❌ Handle common errors gracefully
233
+ try:
234
+ # Tool doesn't exist
235
+ result = await client.call_tool("nonexistent_tool", {})
236
+ except MCPError as e:
237
+ print(f"❌ Tool not found: {e}")
238
+ # Show available tools to help user
239
+ available = client.get_available_tools()
240
+ print(f"Available tools: {available}")
241
+
242
+ try:
243
+ # Wrong arguments
244
+ result = await client.call_tool("read_file", {"wrong_param": "value"})
245
+ except MCPValidationError as e:
246
+ print(f"❌ Invalid arguments: {e}")
247
+
248
+ try:
249
+ # Server error
250
+ result = await client.call_tool("buggy_tool", {})
251
+ except MCPServerError as e:
252
+ print(f"❌ Server error: {e}")
253
+
254
+ try:
255
+ # Timeout
256
+ result = await client.call_tool("slow_tool", {"timeout": 1})
257
+ except MCPTimeoutError as e:
258
+ print(f"❌ Tool took too long: {e}")
259
+
260
+ # ✅ Best practices for tool calls
261
+ async def best_practices():
262
+ # The async context manager connects automatically
263
+ async with MCPClient(config) as client:
264
+
265
+ # 1. Always check if tool exists first
266
+ available_tools = client.get_available_tools()
267
+ if "my_tool" not in available_tools:
268
+ print("❌ Tool not available")
269
+ return
270
+
271
+ # 2. Use try-catch for error handling
272
+ try:
273
+ result = await client.call_tool("my_tool", {"param": "value"})
274
+ print(f"✅ Success: {result}")
275
+ except Exception as e:
276
+ print(f"❌ Error: {e}")
277
+
278
+ # 3. Validate your arguments match what the tool expects
279
+ # (Check tool documentation or use get_available_tools() for details)
280
+ ```
281
+
282
+ #### Tool Discovery
283
+
284
+ **What it does**: Gets detailed information about all the tools available on the MCP server. You can use `client.get_available_tools()` for tool names. For detailed metadata, note that `client.session` is internal and subject to change - use the public API when possible.
285
+
286
+ **Why you need it**: Before you can use tools, you need to know what's available and how to use them. These functions give you that information.
287
+
288
+ **Returns**: List of tool names (get_available_tools) or detailed tool objects (internal session access)
289
+
290
+ ```python
291
+ async def discover_tools():
292
+ # The async context manager connects automatically
293
+ async with MCPClient(config) as client:
294
+
295
+ # Get detailed information about all tools
296
+ # Note: session access is internal and may change
297
+ tools = await client.session.list_tools()
298
+
299
+ print(f"📋 Found {len(tools.tools)} tools on this server:")
300
+ print()
301
+
302
+ for tool in tools.tools:
303
+ print(f"🔧 Tool: {tool.name}")
304
+ print(f" Description: {tool.description}")
305
+
306
+ # Show what parameters this tool accepts
307
+ if hasattr(tool, 'inputSchema') and tool.inputSchema:
308
+ print(f" Parameters: {tool.inputSchema.get('properties', {})}")
309
+
310
+ print() # Empty line for readability
311
+
312
+ # ✅ Practical example - exploring a file server
313
+ async def explore_file_server():
314
+ # The async context manager connects automatically
315
+ async with MCPClient(config) as client:
316
+
317
+ # Note: session access is internal and may change
318
+ tools = await client.session.list_tools()
319
+
320
+ # Look for file-related tools
321
+ file_tools = [tool for tool in tools.tools if 'file' in tool.name.lower()]
322
+
323
+ print("📁 File-related tools:")
324
+ for tool in file_tools:
325
+ print(f" • {tool.name}: {tool.description}")
326
+
327
+ # Show how to use a specific tool
328
+ if file_tools:
329
+ example_tool = file_tools[0]
330
+ print(f"\n📖 How to use '{example_tool.name}':")
331
+ print(f" await client.call_tool('{example_tool.name}', {{...}})")
332
+
333
+ if hasattr(example_tool, 'inputSchema') and example_tool.inputSchema:
334
+ print(f" Required parameters: {example_tool.inputSchema.get('properties', {})}")
335
+
336
+ # ✅ Simple way to just get tool names
337
+ async def get_tool_names():
338
+ # The async context manager connects automatically
339
+ async with MCPClient(config) as client:
340
+ # Quick way to get just the names
341
+ tool_names = client.get_available_tools()
342
+ print(f"Available tools: {tool_names}")
343
+
344
+ # Check if a specific tool exists
345
+ if "read_file" in tool_names:
346
+ print("✅ File reading is available")
347
+ else:
348
+ print("❌ No file reading capability")
349
+ ```
350
+
351
+ ### Resource Operations
352
+
353
+ #### get_resource()
354
+
355
+ **What it does**: Retrieves data or files from the MCP server using a URI (address). Resources are like files or data sources that the server makes available - they could be configuration files, databases, web content, or any other data.
356
+
357
+ **Why you need it**: Some MCP servers provide access to data sources beyond just tools. For example, a server might provide access to configuration files, documentation, or cached data.
358
+
359
+ **Parameters**:
360
+
361
+ - `uri` (required): The resource address (e.g., "file:///config.json", "http://api/data")
362
+
363
+ **Returns**: Resource content (format depends on the resource type)
364
+
365
+ ```python
366
+ from massgen.mcp_tools.exceptions import MCPServerError
367
+ # Optionally import mcp_types for type hints
368
+ # from mcp import types as mcp_types
369
+
370
+ async def resource_access():
371
+ # The async context manager connects automatically
372
+ async with MCPClient(config) as client:
373
+ # ✅ Get a configuration file
374
+ try:
375
+ config_resource = await client.get_resource("file:///app/config.json")
376
+ # Returns ReadResourceResult with contents
377
+ print(f"Config content: {config_resource.contents}")
378
+ except MCPServerError as e:
379
+ print(f"❌ Could not load config: {e}")
380
+
381
+ # ✅ Get web-based data
382
+ try:
383
+ api_data = await client.get_resource("http://internal-api/status")
384
+ print(f"API status: {api_data.contents}")
385
+ except MCPServerError as e:
386
+ print(f"❌ API not accessible: {e}")
387
+
388
+ # ✅ List all available resources first
389
+ available_resources = client.get_available_resources()
390
+ print(f"📋 Available resources:")
391
+ for uri in available_resources:
392
+ print(f" • {uri}")
393
+
394
+ # ✅ Access each available resource
395
+ for uri in available_resources:
396
+ try:
397
+ resource = await client.get_resource(uri)
398
+ print(f"✅ {uri}: {len(str(resource.contents))} characters")
399
+ except Exception as e:
400
+ print(f"❌ {uri}: Failed to load - {e}")
401
+ ```
402
+
403
+ #### get_prompt()
404
+
405
+ **What it does**: Gets a pre-written text template from the server and fills it in with your data. Prompts are like form letters - they have placeholders that get replaced with your specific information.
406
+
407
+ **Why you need it**: Many MCP servers provide useful prompt templates for common tasks like code reviews, text summaries, or translations. Instead of writing these prompts yourself, you can use the server's templates.
408
+
409
+ **Parameters**:
410
+
411
+ - `name` (required): The name of the prompt template (e.g., "code_review")
412
+ - `arguments` (optional): Dictionary of values to fill in the template
413
+
414
+ **Returns**: Prompt object with the generated text
415
+
416
+ ```python
417
+ from massgen.mcp_tools.exceptions import MCPServerError
418
+ # Optionally import mcp_types for type hints
419
+ # from mcp import types as mcp_types
420
+
421
+ async def prompt_usage():
422
+ # The async context manager connects automatically
423
+ async with MCPClient(config) as client:
424
+ # ✅ Use a code review prompt
425
+ try:
426
+ review_prompt = await client.get_prompt("code_review", {
427
+ "language": "python",
428
+ "code": "def hello():\n print('world')",
429
+ "focus": "best_practices"
430
+ })
431
+ # Returns GetPromptResult with messages
432
+ print(f"📝 Generated review prompt:")
433
+ print(review_prompt.messages)
434
+ except MCPServerError as e:
435
+ print(f"❌ Prompt not available: {e}")
436
+
437
+ # ✅ Use a translation prompt
438
+ try:
439
+ translate_prompt = await client.get_prompt("translate", {
440
+ "text": "Hello, how are you?",
441
+ "from_language": "english",
442
+ "to_language": "spanish"
443
+ })
444
+ print(f"🌍 Translation prompt: {translate_prompt.messages}")
445
+ except MCPServerError as e:
446
+ print(f"❌ Translation prompt failed: {e}")
447
+
448
+ # ✅ List available prompts first
449
+ available_prompts = client.get_available_prompts()
450
+ print(f"📋 Available prompts: {available_prompts}")
451
+
452
+ # ✅ Use prompts dynamically
453
+ for prompt_name in available_prompts:
454
+ try:
455
+ # Try with minimal arguments
456
+ prompt = await client.get_prompt(prompt_name, {})
457
+ print(f"✅ {prompt_name}: Template loaded")
458
+ except Exception as e:
459
+ print(f"❌ {prompt_name}: Needs specific arguments - {e}")
460
+ ```
461
+
462
+ ### Health and Monitoring
463
+
464
+ #### health_check()
465
+
466
+ **What it does**: Tests if the connection to the MCP server is still working properly. It's like pinging a server to see if it's still alive and responding.
467
+
468
+ **Why you need it**: Network connections can become unstable, servers can become overloaded, or processes can crash. This function helps you detect these problems before they cause your tools to fail.
469
+
470
+ **Returns**: True if the server is healthy and responding, False if there are problems
471
+
472
+ **What it checks**:
473
+
474
+ 1. Is the connection still active?
475
+ 2. Can the server respond to basic requests?
476
+ 3. Are the server's core functions working?
477
+
478
+ ```python
479
+ async def monitor_health():
480
+ # The async context manager connects automatically
481
+ async with MCPClient(config) as client:
482
+ # ✅ Basic health check
483
+ is_healthy = await client.health_check()
484
+ if is_healthy:
485
+ print("✅ Server is healthy and responding")
486
+ else:
487
+ print("❌ Server health check failed")
488
+
489
+ # ✅ Use health check before important operations
490
+ if await client.health_check():
491
+ # Safe to proceed
492
+ result = await client.call_tool("important_tool", {"data": "value"})
493
+ else:
494
+ print("⚠️ Server unhealthy, attempting reconnect...")
495
+ success = await client.reconnect()
496
+ if success:
497
+ result = await client.call_tool("important_tool", {"data": "value"})
498
+ else:
499
+ print("❌ Could not restore connection")
500
+
501
+ # ✅ Continuous health monitoring
502
+ async def continuous_monitoring():
503
+ # The async context manager connects automatically
504
+ async with MCPClient(config) as client:
505
+ import asyncio
506
+
507
+ # Check health every 30 seconds
508
+ while True:
509
+ try:
510
+ if await client.health_check():
511
+ print("✅ Health check passed")
512
+ else:
513
+ print("⚠️ Health check failed, reconnecting...")
514
+ await client.reconnect()
515
+
516
+ # Wait 30 seconds before next check
517
+ await asyncio.sleep(30)
518
+
519
+ except KeyboardInterrupt:
520
+ print("Stopping health monitoring")
521
+ break
522
+ except Exception as e:
523
+ print(f"❌ Health monitoring error: {e}")
524
+ await asyncio.sleep(5) # Wait before retrying
525
+
526
+ # ✅ Health check with timeout
527
+ async def quick_health_check():
528
+ # The async context manager connects automatically
529
+ async with MCPClient(config) as client:
530
+ try:
531
+ # Set a short timeout for health check
532
+ health_task = asyncio.create_task(client.health_check())
533
+ is_healthy = await asyncio.wait_for(health_task, timeout=5.0)
534
+
535
+ if is_healthy:
536
+ print("✅ Server responded quickly")
537
+ else:
538
+ print("❌ Server is slow or unresponsive")
539
+
540
+ except asyncio.TimeoutError:
541
+ print("❌ Health check timed out - server is very slow")
542
+ except Exception as e:
543
+ print(f"❌ Health check error: {e}")
544
+ ```
545
+
546
+ ### Utility Functions
547
+
548
+ #### get_available_tools()
549
+
550
+ **What it does**: Returns a simple list of tool names available on the server. This is a quick way to see what tools you can use without getting detailed information.
551
+
552
+ **Returns**: List of strings (tool names)
553
+
554
+ ```python
555
+ # The async context manager connects automatically
556
+ async with MCPClient(config) as client:
557
+ # Get just the tool names
558
+ tools = client.get_available_tools()
559
+ print(f"Available tools: {tools}")
560
+ # Output: ['read_file', 'write_file', 'list_directory', 'search_text']
561
+
562
+ # Check if a specific tool exists
563
+ if 'read_file' in tools:
564
+ print("✅ Can read files")
565
+ ```
566
+
567
+ #### get_available_resources()
568
+
569
+ **What it does**: Returns a list of resource URIs (addresses) that you can access on the server. Resources are like files or data sources that the server can provide.
570
+
571
+ **Returns**: List of strings (resource URIs)
572
+
573
+ ```python
574
+ # The async context manager connects automatically
575
+ async with MCPClient(config) as client:
576
+ # Get available resources
577
+ resources = client.get_available_resources()
578
+ print(f"Available resources: {resources}")
579
+ # Output: ['file:///config.json', 'http://api/data', 'memory://cache']
580
+ ```
581
+
582
+ #### get_available_prompts()
583
+
584
+ **What it does**: Returns a list of prompt templates available on the server. Prompts are pre-written text templates that can be customized with your data.
585
+
586
+ **Returns**: List of strings (prompt names)
587
+
588
+ ```python
589
+ # The async context manager connects automatically
590
+ async with MCPClient(config) as client:
591
+ # Get available prompts
592
+ prompts = client.get_available_prompts()
593
+ print(f"Available prompts: {prompts}")
594
+ # Output: ['code_review', 'summarize_text', 'translate']
595
+ ```
596
+
597
+ #### is_connected()
598
+
599
+ **What it does**: Checks if the client is currently connected to the MCP server. This is useful for verifying the connection status before trying to use tools.
600
+
601
+ **Returns**: True if connected, False if not connected
602
+
603
+ ```python
604
+ # The async context manager connects automatically
605
+ async with MCPClient(config) as client:
606
+ # After automatic connection
607
+ print(f"Connected: {client.is_connected()}") # True
608
+
609
+ # Use in conditional logic
610
+ if client.is_connected():
611
+ result = await client.call_tool("some_tool", {})
612
+ else:
613
+ print("❌ Not connected - cannot use tools")
614
+ await client.connect()
615
+ ```
616
+
617
+ ## MultiMCPClient Class
618
+
619
+ The `MultiMCPClient` class manages connections to multiple MCP servers simultaneously, providing unified access to tools and resources across all connected servers.
620
+
621
+ ### Initialization and Connection
622
+
623
+ #### MultiMCPClient()
624
+
625
+ Creates a MultiMCPClient instance and connects to multiple MCP servers based on configuration.
626
+
627
+ ```python
628
+ from massgen.mcp_tools import MultiMCPClient
629
+
630
+ async def multi_server_setup():
631
+ # Configuration for multiple servers - use list format
632
+ servers_config = [
633
+ {
634
+ "name": "file_server",
635
+ "type": "stdio",
636
+ "command": "python",
637
+ "args": ["-m", "file_mcp_server"],
638
+ "security": {
639
+ "level": "strict"
640
+ }
641
+ },
642
+ {
643
+ "name": "web_server",
644
+ "type": "streamable-http",
645
+ "url": "http://localhost:8000/mcp",
646
+ "security": {
647
+ "level": "moderate"
648
+ }
649
+ }
650
+ ]
651
+
652
+ # Create and connect to all servers
653
+ multi_client = MultiMCPClient(servers_config)
654
+ await multi_client.connect()
655
+
656
+ # Alternative: Transform dict format using validator
657
+ # from massgen.mcp_tools import MCPConfigValidator
658
+ # dict_config = {"server1": {...}, "server2": {...}}
659
+ # validated_config = MCPConfigValidator.validate_backend_mcp_config(dict_config)
660
+ # multi_client = MultiMCPClient(validated_config)
661
+ # await multi_client.connect()
662
+
663
+ try:
664
+ # Use the multi-client
665
+ tools = list(multi_client.tools.keys())
666
+ print(f"Total tools available: {len(tools)}")
667
+ finally:
668
+ await multi_client.disconnect()
669
+ ```
670
+
671
+ ### Tool Routing
672
+
673
+ Tools in multi-server setups are prefixed with the server name for disambiguation.
674
+
675
+ ```python
676
+ async def multi_server_tools():
677
+ multi_client = MultiMCPClient(servers_config)
678
+ await multi_client.connect()
679
+
680
+ try:
681
+ # Call tool from specific server
682
+ file_result = await multi_client.call_tool("mcp__file_server__read_file", {
683
+ "path": "example.txt"
684
+ })
685
+
686
+ web_result = await multi_client.call_tool("mcp__web_server__fetch_url", {
687
+ "url": "https://api.example.com/data"
688
+ })
689
+
690
+ # List tools by server - filter by server prefix
691
+ file_tools = [t for t in multi_client.tools if t.startswith("mcp__file_server__")]
692
+ web_tools = [t for t in multi_client.tools if t.startswith("mcp__web_server__")]
693
+
694
+ finally:
695
+ await multi_client.disconnect()
696
+ ```
697
+
698
+ ### Circuit Breaker Integration
699
+
700
+ The multi-client includes circuit breaker functionality for handling server failures.
701
+
702
+ ```python
703
+ async def circuit_breaker_example():
704
+ # Configuration with circuit breaker settings
705
+ config_with_cb = [
706
+ {
707
+ "name": "file_server",
708
+ "type": "stdio",
709
+ "command": "python",
710
+ "args": ["-m", "unreliable_server"],
711
+ "circuit_breaker": {
712
+ "failure_threshold": 5,
713
+ "recovery_timeout": 60,
714
+ "expected_exception": "MCPConnectionError"
715
+ }
716
+ }
717
+ ]
718
+
719
+ multi_client = MultiMCPClient(config_with_cb)
720
+ await multi_client.connect()
721
+
722
+ try:
723
+ # Circuit breaker will handle failures automatically
724
+ for i in range(10):
725
+ try:
726
+ result = await multi_client.call_tool("mcp__file_server__unstable_tool", {})
727
+ print(f"Success: {result}")
728
+ except Exception as e:
729
+ print(f"Handled by circuit breaker: {e}")
730
+
731
+ finally:
732
+ await multi_client.disconnect()
733
+ ```
734
+
735
+ ## Configuration Integration
736
+
737
+ ### Config Validator Integration
738
+
739
+ The client integrates with the config validator for comprehensive validation.
740
+
741
+ ```python
742
+ from massgen.mcp_tools import MCPConfigValidator, validate_mcp_integration
743
+
744
+ async def validated_client():
745
+ # Raw configuration
746
+ raw_config = {
747
+ "type": "streamable-http",
748
+ "url": "http://localhost:8000/mcp",
749
+ "timeout": "invalid_timeout" # This will be caught
750
+ }
751
+
752
+ try:
753
+ # Validate configuration before creating client
754
+ validated_config = MCPConfigValidator.validate_server_config(raw_config)
755
+ client = MCPClient(validated_config)
756
+ await client.connect()
757
+ except MCPConfigurationError as e:
758
+ print(f"Configuration error: {e}")
759
+ ```
760
+
761
+ ### Timeout Configuration
762
+
763
+ Configure timeouts for different operations:
764
+
765
+ ```python
766
+ config_with_timeouts = {
767
+ "name": "slow_server",
768
+ "type": "stdio",
769
+ "command": "python",
770
+ "args": ["-m", "slow_server"],
771
+ "timeout": 60, # General timeout
772
+ "http_read_timeout": 300 # HTTP read timeout for streamable-http transport
773
+ }
774
+ ```
775
+
776
+ ## Practical Examples
777
+
778
+ ### Example 1: File Processing Server
779
+
780
+ ```python
781
+ # Based on massgen/configs/gemini_mcp_example.yaml
782
+ async def file_processing_example():
783
+ config = {
784
+ "name": "file_processor",
785
+ "type": "stdio",
786
+ "command": "python",
787
+ "args": ["-m", "file_processor_server"],
788
+ "security": {
789
+ "level": "strict"
790
+ },
791
+ "timeout": 30
792
+ }
793
+
794
+ # The async context manager connects automatically
795
+ async with MCPClient(config) as client:
796
+ # Process multiple files
797
+ files = ["doc1.txt", "doc2.txt", "doc3.txt"]
798
+ results = []
799
+
800
+ for file_path in files:
801
+ try:
802
+ result = await client.call_tool("process_file", {
803
+ "path": file_path,
804
+ "operation": "analyze"
805
+ })
806
+ results.append(result)
807
+ except MCPServerError as e:
808
+ print(f"Failed to process {file_path}: {e}")
809
+
810
+ return results
811
+ ```
812
+
813
+ ### Example 2: Multi-Server Coordination
814
+
815
+ ```python
816
+ # Based on massgen/configs/claude_code_discord_mcp_example.yaml
817
+ async def multi_server_coordination():
818
+ servers_config = [
819
+ {
820
+ "name": "code_analyzer",
821
+ "type": "stdio",
822
+ "command": "python",
823
+ "args": ["-m", "code_analysis_server"],
824
+ "security": {
825
+ "level": "moderate"
826
+ }
827
+ },
828
+ {
829
+ "name": "discord_bot",
830
+ "type": "streamable-http",
831
+ "url": "http://localhost:8001/mcp",
832
+ "headers": {"Authorization": "Bearer discord-token"},
833
+ "security": {
834
+ "level": "strict"
835
+ }
836
+ }
837
+ ]
838
+
839
+ multi_client = MultiMCPClient(servers_config)
840
+ await multi_client.connect()
841
+
842
+ try:
843
+ # Analyze code
844
+ analysis = await multi_client.call_tool("mcp__code_analyzer__analyze_python", {
845
+ "file_path": "main.py"
846
+ })
847
+
848
+ # Send results to Discord
849
+ await multi_client.call_tool("mcp__discord_bot__send_message", {
850
+ "channel": "code-reviews",
851
+ "content": f"Analysis complete: {analysis['summary']}"
852
+ })
853
+
854
+ finally:
855
+ await multi_client.disconnect()
856
+ ```
857
+
858
+ ## Best Practices
859
+
860
+ ### Error Handling
861
+
862
+ Always use proper exception handling with specific exception types:
863
+
864
+ ```python
865
+ from massgen.mcp_tools.exceptions import (
866
+ MCPConnectionError, MCPServerError, MCPConfigurationError,
867
+ MCPTimeoutError, MCPValidationError
868
+ )
869
+
870
+ async def robust_client_usage():
871
+ # The async context manager connects automatically
872
+ async with MCPClient(config) as client:
873
+ try:
874
+ result = await client.call_tool("example_tool", args)
875
+
876
+ except MCPConnectionError:
877
+ # Handle connection issues
878
+ await client.reconnect()
879
+
880
+ except MCPServerError as e:
881
+ # Handle tool-specific errors
882
+ print(f"Tool failed: {e}")
883
+
884
+ except MCPConfigurationError as e:
885
+ # Handle configuration validation failures
886
+ print(f"Configuration error: {e}")
887
+
888
+ except MCPTimeoutError:
889
+ # Handle timeouts
890
+ print("Operation timed out")
891
+ ```
892
+
893
+ ### Connection Pooling
894
+
895
+ For high-throughput applications, consider connection pooling:
896
+
897
+ ```python
898
+ class MCPConnectionPool:
899
+ def __init__(self, config, pool_size=5):
900
+ self.config = config
901
+ self.pool_size = pool_size
902
+ self.connections = []
903
+
904
+ async def get_connection(self):
905
+ if self.connections:
906
+ return self.connections.pop()
907
+ return MCPClient(self.config)
908
+
909
+ async def return_connection(self, client):
910
+ if len(self.connections) < self.pool_size:
911
+ self.connections.append(client)
912
+ else:
913
+ await client.disconnect()
914
+ ```
915
+
916
+ ### Resource Cleanup
917
+
918
+ Always ensure proper resource cleanup:
919
+
920
+ ```python
921
+ async def proper_cleanup():
922
+ client = None
923
+ try:
924
+ client = MCPClient(config)
925
+ await client.connect()
926
+ # ... operations
927
+ finally:
928
+ if client:
929
+ await client.disconnect()
930
+ ```
931
+
932
+ ## Integration with MassGen
933
+
934
+ The MCP client integrates seamlessly with MassGen's orchestration system:
935
+
936
+ ```python
937
+ from massgen.orchestrator import MassGenOrchestrator
938
+
939
+ async def massgen_integration():
940
+ # MassGen automatically manages MCP clients based on configuration
941
+ orchestrator = MassGenOrchestrator(config_path="config.yaml")
942
+
943
+ # MCP tools are available through the orchestrator
944
+ result = await orchestrator.execute_task({
945
+ "task": "analyze_code",
946
+ "mcp_tools": ["mcp__code_analyzer__lint", "mcp__code_analyzer__security_scan"]
947
+ })
948
+ ```
949
+
950
+ This integration allows MassGen to automatically discover and use MCP tools as part of its task execution pipeline.