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,1165 @@
1
+ # MCP Exception System Documentation
2
+
3
+ The MCP (Model Context Protocol) exception system provides a comprehensive error handling framework with structured context preservation, automatic sanitization of sensitive information, and enhanced debugging capabilities for MCP integrations.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [Exception Hierarchy](#exception-hierarchy)
9
+ - [Base Exception Class](#base-exception-class)
10
+ - [Specialized Exception Classes](#specialized-exception-classes)
11
+ - [Utility Functions](#utility-functions)
12
+ - [Usage Examples](#usage-examples)
13
+ - [Error Context and Sanitization](#error-context-and-sanitization)
14
+ - [Integration Patterns](#integration-patterns)
15
+ - [Troubleshooting Guide](#troubleshooting-guide)
16
+ - [Best Practices](#best-practices)
17
+
18
+ ## Overview
19
+
20
+ The MCP exception system is built around a hierarchical structure that provides:
21
+
22
+ - **Structured Error Information**: All exceptions carry detailed context about the error condition
23
+ - **Automatic Sanitization**: Sensitive information is automatically redacted from error contexts
24
+ - **Enhanced Debugging**: Rich error information with timestamps, error codes, and contextual data
25
+ - **Consistent Logging**: Standardized error logging with structured data
26
+ - **Error Chain Formatting**: Clear representation of exception chains for debugging
27
+
28
+ ### Architecture
29
+
30
+ ```
31
+ MCPError (Base)
32
+ ├── MCPConnectionError (Connection failures)
33
+ ├── MCPServerError (Server-side errors)
34
+ ├── MCPValidationError (Input validation)
35
+ ├── MCPTimeoutError (Operation timeouts)
36
+ ├── MCPAuthenticationError (Auth failures)
37
+ ├── MCPConfigurationError (Config issues)
38
+ └── MCPResourceError (Resource operations)
39
+ ```
40
+
41
+ ## Exception Hierarchy
42
+
43
+ ### MCPError (Base Class)
44
+
45
+ The foundation of all MCP exceptions, providing core functionality for context preservation and sanitization.
46
+
47
+ **Constructor Parameters:**
48
+ - `message` (str): Human-readable error message
49
+ - `context` (Optional[Dict[str, Any]]): Additional error context
50
+ - `error_code` (Optional[str]): Machine-readable error code
51
+ - `timestamp` (Optional[datetime]): Error timestamp (defaults to current UTC time)
52
+
53
+ **Instance Attributes:**
54
+ - `context`: Sanitized error context dictionary
55
+ - `error_code`: Optional error code for programmatic handling
56
+ - `timestamp`: UTC timestamp when error occurred
57
+ - `original_message`: Original error message before formatting
58
+
59
+ **Methods:**
60
+ - `to_dict()`: Convert exception to dictionary representation
61
+ - `log_error(logger)`: Log error with structured context
62
+ - `_sanitize_context(context)`: Remove sensitive information from context
63
+
64
+ ## Base Exception Class
65
+
66
+ ### MCPError
67
+
68
+ ```python
69
+ from massgen.mcp_tools.exceptions import MCPError
70
+
71
+ # Basic usage
72
+ error = MCPError(
73
+ "Connection failed",
74
+ context={"server": "example-server", "port": 8080},
75
+ error_code="CONN_FAILED"
76
+ )
77
+
78
+ # Convert to dictionary for logging/serialization
79
+ error_dict = error.to_dict()
80
+ # {
81
+ # 'error_type': 'MCPError',
82
+ # 'message': 'Connection failed',
83
+ # 'error_code': 'CONN_FAILED',
84
+ # 'context': {'server': 'example-server', 'port': 8080},
85
+ # 'timestamp': '2024-01-15T10:30:00.000000+00:00'
86
+ # }
87
+
88
+ # Log the error
89
+ import logging
90
+ logger = logging.getLogger(__name__)
91
+ error.log_error(logger)
92
+ ```
93
+
94
+ ### Context Sanitization
95
+
96
+ The base class automatically sanitizes sensitive information:
97
+
98
+ ```python
99
+ # Sensitive data is automatically redacted
100
+ error = MCPError(
101
+ "Authentication failed",
102
+ context={
103
+ "username": "john_doe",
104
+ "password": "secret123", # Will be redacted
105
+ "api_key": "sk-1234567890", # Will be redacted
106
+ "server": "api.example.com"
107
+ }
108
+ )
109
+
110
+ print(error.context)
111
+ # {
112
+ # 'username': 'john_doe',
113
+ # 'password': '[REDACTED]',
114
+ # 'api_key': '[REDACTED]',
115
+ # 'server': 'api.example.com'
116
+ # }
117
+ ```
118
+
119
+ ## Specialized Exception Classes
120
+
121
+ ### MCPConnectionError
122
+
123
+ Raised when MCP server connections fail. Includes connection-specific details for debugging and retry logic.
124
+
125
+ **Additional Constructor Parameters:**
126
+ - `server_name` (Optional[str]): Name of the server
127
+ - `transport_type` (Optional[str]): Transport type (stdio, streamable-http)
128
+ - `host` (Optional[str]): Server hostname
129
+ - `port` (Optional[int]): Server port
130
+ - `retry_count` (Optional[int]): Number of retry attempts
131
+
132
+ **Example:**
133
+ ```python
134
+ from massgen.mcp_tools.exceptions import MCPConnectionError
135
+
136
+ # Connection failure with detailed context
137
+ error = MCPConnectionError(
138
+ "Failed to connect to MCP server",
139
+ server_name="file-manager",
140
+ transport_type="stdio",
141
+ host="localhost",
142
+ port=8080,
143
+ retry_count=3,
144
+ error_code="CONN_TIMEOUT"
145
+ )
146
+
147
+ # Access connection-specific attributes
148
+ print(f"Server: {error.server_name}")
149
+ print(f"Transport: {error.transport_type}")
150
+ print(f"Retries: {error.retry_count}")
151
+ ```
152
+
153
+ ### MCPServerError
154
+
155
+ Raised when MCP servers return errors. Includes server error codes and response data.
156
+
157
+ **Additional Constructor Parameters:**
158
+ - `code` (Optional[Union[int, str]]): Server error code
159
+ - `server_name` (Optional[str]): Name of the server
160
+ - `http_status` (Optional[int]): HTTP status code (for HTTP transport)
161
+ - `response_data` (Optional[Dict[str, Any]]): Server response data
162
+
163
+ **Example:**
164
+ ```python
165
+ from massgen.mcp_tools.exceptions import MCPServerError
166
+
167
+ # Server error with response details
168
+ error = MCPServerError(
169
+ "Tool execution failed",
170
+ code=-32603,
171
+ server_name="code-executor",
172
+ http_status=500,
173
+ response_data={"error": "Internal server error", "details": "..."},
174
+ error_code="TOOL_EXEC_FAILED"
175
+ )
176
+ ```
177
+
178
+ ### MCPValidationError
179
+
180
+ Raised when configuration or input validation fails. Includes detailed validation information.
181
+
182
+ **Additional Constructor Parameters:**
183
+ - `field` (Optional[str]): Field that failed validation
184
+ - `value` (Optional[Any]): Invalid value
185
+ - `expected_type` (Optional[str]): Expected data type
186
+ - `validation_rule` (Optional[str]): Validation rule that failed
187
+
188
+ **Example:**
189
+ ```python
190
+ from massgen.mcp_tools.exceptions import MCPValidationError
191
+
192
+ # Validation error with field details
193
+ error = MCPValidationError(
194
+ "Invalid tool argument type",
195
+ field="timeout",
196
+ value="not_a_number",
197
+ expected_type="int",
198
+ validation_rule="must_be_positive_integer"
199
+ )
200
+ ```
201
+
202
+ ### MCPTimeoutError
203
+
204
+ Raised when MCP operations timeout. Includes timing information for retry logic.
205
+
206
+ **Additional Constructor Parameters:**
207
+ - `timeout_seconds` (Optional[float]): Configured timeout
208
+ - `operation` (Optional[str]): Operation that timed out
209
+ - `elapsed_seconds` (Optional[float]): Actual elapsed time
210
+ - `server_name` (Optional[str]): Server name
211
+
212
+ **Example:**
213
+ ```python
214
+ from massgen.mcp_tools.exceptions import MCPTimeoutError
215
+
216
+ # Timeout error with timing details
217
+ error = MCPTimeoutError(
218
+ "Tool call timed out",
219
+ timeout_seconds=30.0,
220
+ operation="call_tool(file_read)",
221
+ elapsed_seconds=30.5,
222
+ server_name="file-manager"
223
+ )
224
+ ```
225
+
226
+ ### MCPAuthenticationError
227
+
228
+ Raised when authentication or authorization fails. Excludes sensitive authentication data.
229
+
230
+ **Additional Constructor Parameters:**
231
+ - `auth_type` (Optional[str]): Authentication type
232
+ - `username` (Optional[str]): Username (non-sensitive)
233
+ - `server_name` (Optional[str]): Server name
234
+ - `permission_required` (Optional[str]): Required permission
235
+
236
+ **Example:**
237
+ ```python
238
+ from massgen.mcp_tools.exceptions import MCPAuthenticationError
239
+
240
+ # Authentication error without exposing credentials
241
+ error = MCPAuthenticationError(
242
+ "Insufficient permissions",
243
+ auth_type="api_key",
244
+ username="service_account",
245
+ server_name="secure-server",
246
+ permission_required="file:write"
247
+ )
248
+ ```
249
+
250
+ ### MCPConfigurationError
251
+
252
+ Raised when MCP configuration is invalid or missing. Includes configuration context.
253
+
254
+ **Additional Constructor Parameters:**
255
+ - `config_file` (Optional[str]): Configuration file path
256
+ - `config_section` (Optional[str]): Configuration section
257
+ - `missing_keys` (Optional[list]): List of missing required keys
258
+
259
+ **Example:**
260
+ ```python
261
+ from massgen.mcp_tools.exceptions import MCPConfigurationError
262
+
263
+ # Configuration error with file details
264
+ error = MCPConfigurationError(
265
+ "Missing required configuration keys",
266
+ config_file="/path/to/config.yaml",
267
+ config_section="mcp_servers",
268
+ missing_keys=["name", "command"]
269
+ )
270
+ ```
271
+
272
+ ### MCPResourceError
273
+
274
+ Raised when MCP resource operations fail. Includes resource and operation details.
275
+
276
+ **Additional Constructor Parameters:**
277
+ - `resource_type` (Optional[str]): Type of resource
278
+ - `resource_id` (Optional[str]): Resource identifier
279
+ - `operation` (Optional[str]): Failed operation
280
+ - `server_name` (Optional[str]): Server name
281
+
282
+ **Example:**
283
+ ```python
284
+ from massgen.mcp_tools.exceptions import MCPResourceError
285
+
286
+ # Resource operation error
287
+ error = MCPResourceError(
288
+ "Failed to read resource",
289
+ resource_type="file",
290
+ resource_id="file:///path/to/file.txt",
291
+ operation="read",
292
+ server_name="file-server"
293
+ )
294
+ ```
295
+
296
+ ## Utility Functions
297
+
298
+ ### handle_mcp_error Decorator (Sync Only)
299
+
300
+ Automatically catches and logs MCP errors for synchronous functions, converting unexpected exceptions to MCPError.
301
+
302
+ **Note:** This decorator is for synchronous functions only. For async functions, use `async_handle_mcp_error` or manual error handling.
303
+
304
+ ```python
305
+ from massgen.mcp_tools.exceptions import handle_mcp_error, MCPError
306
+
307
+ @handle_mcp_error
308
+ def risky_sync_operation():
309
+ # This function's exceptions will be automatically handled
310
+ raise ValueError("Something went wrong")
311
+
312
+ try:
313
+ risky_sync_operation()
314
+ except MCPError as e:
315
+ # ValueError was converted to MCPError and logged
316
+ print(f"Caught MCP error: {e}")
317
+ ```
318
+
319
+ ### async_handle_mcp_error Decorator
320
+
321
+ Automatically catches and logs MCP errors for asynchronous functions, properly awaiting the result before handling exceptions.
322
+
323
+ ```python
324
+ from massgen.mcp_tools.exceptions import async_handle_mcp_error, MCPError
325
+
326
+ @async_handle_mcp_error
327
+ async def risky_async_operation():
328
+ # This async function's exceptions will be automatically handled
329
+ raise ValueError("Something went wrong")
330
+
331
+ try:
332
+ await risky_async_operation()
333
+ except MCPError as e:
334
+ # ValueError was converted to MCPError and logged
335
+ print(f"Caught MCP error: {e}")
336
+ ```
337
+
338
+ ### Manual Async Error Handling
339
+
340
+ For cases where you prefer manual error handling in async functions:
341
+
342
+ ```python
343
+ from massgen.mcp_tools.exceptions import MCPError
344
+
345
+ async def manual_async_operation():
346
+ try:
347
+ # Your async operation here
348
+ raise ValueError("Something went wrong")
349
+ except MCPError as e:
350
+ e.log_error()
351
+ raise
352
+ except Exception as e:
353
+ # Convert unexpected exceptions to MCPError
354
+ mcp_error = MCPError(
355
+ f"Unexpected error in manual_async_operation: {str(e)}",
356
+ context={"function": "manual_async_operation", "original_error": type(e).__name__}
357
+ )
358
+ mcp_error.log_error()
359
+ raise mcp_error from e
360
+
361
+ try:
362
+ await manual_async_operation()
363
+ except MCPError as e:
364
+ print(f"Caught MCP error: {e}")
365
+ ```
366
+
367
+ ### format_error_chain Function
368
+
369
+ Formats exception chains for better error reporting.
370
+
371
+ ```python
372
+ from massgen.mcp_tools.exceptions import format_error_chain, MCPConnectionError
373
+
374
+ try:
375
+ # Nested exception scenario
376
+ try:
377
+ raise ConnectionError("Network unreachable")
378
+ except ConnectionError as e:
379
+ raise MCPConnectionError("Failed to connect to server") from e
380
+ except MCPConnectionError as e:
381
+ error_chain = format_error_chain(e)
382
+ print(error_chain)
383
+ # Output: "MCPConnectionError: Failed to connect to server -> ConnectionError: Network unreachable"
384
+ ```
385
+
386
+ ## Usage Examples
387
+
388
+ **Note on Command Configuration**: The examples below use the preferred `command` + `args` pattern for MCP server configuration (e.g., `"command": "python", "args": ["-m", "server_module"]`). While the security validator also accepts a single `command` field as a string or list, the separate `command` and `args` fields provide better clarity and are recommended for consistency with other MCP tools documentation.
389
+
390
+ ### Basic Exception Handling
391
+
392
+ ```python
393
+ import asyncio
394
+ from massgen.mcp_tools.client import MCPClient
395
+ from massgen.mcp_tools.exceptions import (
396
+ MCPConnectionError, MCPServerError, MCPTimeoutError, MCPError
397
+ )
398
+
399
+ async def connect_with_error_handling():
400
+ server_config = {
401
+ "name": "example-server",
402
+ "type": "stdio",
403
+ "command": "python",
404
+ "args": ["-m", "example_server"]
405
+ }
406
+
407
+ try:
408
+ async with MCPClient(server_config) as client:
409
+ result = await client.call_tool("example_tool", {"param": "value"})
410
+ return result
411
+
412
+ except MCPConnectionError as e:
413
+ print(f"Connection failed: {e}")
414
+ print(f"Server: {e.server_name}, Transport: {e.transport_type}")
415
+ # Implement retry logic
416
+
417
+ except MCPTimeoutError as e:
418
+ print(f"Operation timed out: {e}")
419
+ print(f"Operation: {e.operation}, Timeout: {e.timeout_seconds}s")
420
+ # Implement timeout handling
421
+
422
+ except MCPServerError as e:
423
+ print(f"Server error: {e}")
424
+ print(f"Server code: {e.code}, HTTP status: {e.http_status}")
425
+ # Handle server-side errors
426
+
427
+ except MCPError as e:
428
+ print(f"General MCP error: {e}")
429
+ e.log_error() # Log with structured context
430
+ # Handle any other MCP errors
431
+ ```
432
+
433
+ ### Error Recovery Patterns
434
+
435
+ ```python
436
+ import asyncio
437
+ from massgen.mcp_tools.exceptions import MCPConnectionError, MCPTimeoutError
438
+
439
+ async def robust_tool_call(client, tool_name, arguments, max_retries=3):
440
+ """Call tool with automatic retry on certain errors."""
441
+
442
+ for attempt in range(max_retries):
443
+ try:
444
+ return await client.call_tool(tool_name, arguments)
445
+
446
+ except MCPTimeoutError as e:
447
+ if attempt < max_retries - 1:
448
+ wait_time = 2 ** attempt # Exponential backoff
449
+ print(f"Timeout on attempt {attempt + 1}, retrying in {wait_time}s...")
450
+ await asyncio.sleep(wait_time)
451
+ continue
452
+ else:
453
+ print(f"Tool call failed after {max_retries} attempts")
454
+ raise
455
+
456
+ except MCPConnectionError as e:
457
+ if attempt < max_retries - 1:
458
+ print(f"Connection error on attempt {attempt + 1}, reconnecting...")
459
+ await client.reconnect()
460
+ continue
461
+ else:
462
+ raise
463
+
464
+ except Exception as e:
465
+ # Don't retry on other errors
466
+ print(f"Non-retryable error: {e}")
467
+ raise
468
+ ```
469
+
470
+ ### Structured Error Logging
471
+
472
+ ```python
473
+ import logging
474
+ import json
475
+ from massgen.mcp_tools.exceptions import MCPError
476
+
477
+ # Configure structured logging
478
+ logging.basicConfig(
479
+ level=logging.INFO,
480
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
481
+ )
482
+
483
+ class StructuredErrorHandler(logging.Handler):
484
+ """Custom handler for structured MCP error logging."""
485
+
486
+ def emit(self, record):
487
+ if hasattr(record, 'mcp_error'):
488
+ error_data = record.mcp_error
489
+ structured_log = {
490
+ 'timestamp': record.created,
491
+ 'level': record.levelname,
492
+ 'message': record.getMessage(),
493
+ 'mcp_error': error_data
494
+ }
495
+ print(json.dumps(structured_log, indent=2))
496
+
497
+ # Set up logger with structured handler
498
+ logger = logging.getLogger('mcp_client')
499
+ logger.addHandler(StructuredErrorHandler())
500
+
501
+ # Use with MCP errors
502
+ try:
503
+ # Some MCP operation
504
+ pass
505
+ except MCPError as e:
506
+ e.log_error(logger) # Will use structured logging
507
+ ```
508
+
509
+ ## Error Context and Sanitization
510
+
511
+ ### Automatic Sanitization
512
+
513
+ The exception system automatically removes sensitive information from error contexts:
514
+
515
+ ```python
516
+ from massgen.mcp_tools.exceptions import MCPError
517
+
518
+ # Sensitive keys are automatically detected and redacted
519
+ sensitive_context = {
520
+ "username": "user123",
521
+ "password": "secret", # Redacted
522
+ "api_key": "sk-abc123", # Redacted
523
+ "auth_token": "bearer...", # Redacted
524
+ "secret_key": "hidden", # Redacted
525
+ "credential": "creds", # Redacted
526
+ "server_url": "https://api.example.com", # Preserved
527
+ "timeout": 30 # Preserved
528
+ }
529
+
530
+ error = MCPError("Operation failed", context=sensitive_context)
531
+
532
+ # Only non-sensitive data is preserved
533
+ print(error.context)
534
+ # {
535
+ # 'username': 'user123',
536
+ # 'password': '[REDACTED]',
537
+ # 'api_key': '[REDACTED]',
538
+ # 'auth_token': '[REDACTED]',
539
+ # 'secret_key': '[REDACTED]',
540
+ # 'credential': '[REDACTED]',
541
+ # 'server_url': 'https://api.example.com',
542
+ # 'timeout': 30
543
+ # }
544
+ ```
545
+
546
+ ### Custom Context Handling
547
+
548
+ ```python
549
+ from massgen.mcp_tools.exceptions import MCPError
550
+
551
+ class CustomMCPError(MCPError):
552
+ """Custom MCP error with additional sanitization."""
553
+
554
+ def _sanitize_context(self, context):
555
+ # Call parent sanitization first
556
+ sanitized = super()._sanitize_context(context)
557
+
558
+ # Add custom sanitization rules
559
+ custom_sensitive = {'internal_id', 'session_token', 'private_key'}
560
+
561
+ for key, value in sanitized.items():
562
+ if any(sensitive in key.lower() for sensitive in custom_sensitive):
563
+ sanitized[key] = "[CUSTOM_REDACTED]"
564
+
565
+ return sanitized
566
+
567
+ # Usage
568
+ error = CustomMCPError(
569
+ "Custom error",
570
+ context={
571
+ "internal_id": "12345",
572
+ "session_token": "sess_abc",
573
+ "public_data": "visible"
574
+ }
575
+ )
576
+
577
+ print(error.context)
578
+ # {
579
+ # 'internal_id': '[CUSTOM_REDACTED]',
580
+ # 'session_token': '[CUSTOM_REDACTED]',
581
+ # 'public_data': 'visible'
582
+ # }
583
+ ```
584
+
585
+ ## Integration Patterns
586
+
587
+ ### Circuit Breaker Integration
588
+
589
+ The exception system integrates with the circuit breaker for failure tracking:
590
+
591
+ ```python
592
+ from massgen.mcp_tools.circuit_breaker import MCPCircuitBreaker
593
+ from massgen.mcp_tools.exceptions import MCPConnectionError, MCPServerError
594
+
595
+ async def call_with_circuit_breaker(client, circuit_breaker, server_name, tool_name, args):
596
+ """Call tool with circuit breaker protection."""
597
+
598
+ # Check if server should be skipped
599
+ if circuit_breaker.should_skip_server(server_name):
600
+ raise MCPConnectionError(
601
+ f"Server {server_name} is circuit broken",
602
+ server_name=server_name,
603
+ context={"circuit_breaker": "open"}
604
+ )
605
+
606
+ try:
607
+ result = await client.call_tool(tool_name, args)
608
+ # Record success
609
+ circuit_breaker.record_success(server_name)
610
+ return result
611
+
612
+ except (MCPConnectionError, MCPServerError) as e:
613
+ # Record failure for circuit breaker
614
+ circuit_breaker.record_failure(server_name)
615
+
616
+ # Add circuit breaker context to error
617
+ e.context = e.context or {}
618
+ e.context.update({
619
+ "circuit_breaker_failures": circuit_breaker.get_server_status(server_name)[0]
620
+ })
621
+
622
+ raise
623
+ ```
624
+
625
+ ### Configuration Validator Integration
626
+
627
+ Exception handling with configuration validation:
628
+
629
+ ```python
630
+ from massgen.mcp_tools.config_validator import MCPConfigValidator
631
+ from massgen.mcp_tools.exceptions import MCPConfigurationError, MCPValidationError
632
+
633
+ def validate_and_handle_config(config):
634
+ """Validate configuration with proper error handling."""
635
+
636
+ try:
637
+ validated_config = MCPConfigValidator.validate_server_config(config)
638
+ return validated_config
639
+
640
+ except MCPConfigurationError as e:
641
+ # Configuration-specific error handling
642
+ print(f"Configuration error: {e}")
643
+
644
+ if e.missing_keys:
645
+ print(f"Missing required keys: {e.missing_keys}")
646
+
647
+ if e.config_file:
648
+ print(f"Check configuration file: {e.config_file}")
649
+
650
+ # Log structured error
651
+ e.log_error()
652
+ raise
653
+
654
+ except MCPValidationError as e:
655
+ # Validation-specific error handling
656
+ print(f"Validation error in field '{e.field}': {e}")
657
+ print(f"Expected: {e.expected_type}, Got: {type(e.value).__name__}")
658
+
659
+ # Log with additional context
660
+ e.log_error()
661
+ raise
662
+ ```
663
+
664
+ ## Troubleshooting Guide
665
+
666
+ ### Common Error Scenarios
667
+
668
+ #### Connection Failures
669
+
670
+ **Symptoms:**
671
+ - `MCPConnectionError` with transport-specific details
672
+ - Connection timeouts or refused connections
673
+
674
+ **Common Causes:**
675
+ 1. **Stdio Transport Issues:**
676
+ - Incorrect command path
677
+ - Missing executable permissions
678
+ - Environment variable issues
679
+
680
+ 2. **HTTP Transport Issues:**
681
+ - Invalid URL or port
682
+ - Network connectivity problems
683
+ - SSL/TLS certificate issues
684
+
685
+ **Resolution Steps:**
686
+ ```python
687
+ # Debug stdio connection
688
+ try:
689
+ async with MCPClient(stdio_config) as client:
690
+ pass
691
+ except MCPConnectionError as e:
692
+ if e.transport_type == "stdio":
693
+ print(f"Check command: {stdio_config.get('command')}")
694
+ print(f"Check environment: {stdio_config.get('env', {})}")
695
+
696
+ # Test command manually
697
+ import subprocess
698
+ try:
699
+ result = subprocess.run(
700
+ stdio_config['command'],
701
+ capture_output=True,
702
+ text=True,
703
+ timeout=10
704
+ )
705
+ print(f"Command output: {result.stdout}")
706
+ print(f"Command errors: {result.stderr}")
707
+ except Exception as cmd_error:
708
+ print(f"Command execution failed: {cmd_error}")
709
+
710
+ # Debug HTTP connection
711
+ try:
712
+ async with MCPClient(http_config) as client:
713
+ pass
714
+ except MCPConnectionError as e:
715
+ if e.transport_type == "streamable-http":
716
+ print(f"Check URL: {http_config.get('url')}")
717
+ print(f"Check headers: {http_config.get('headers', {})}")
718
+
719
+ # Test HTTP connectivity
720
+ import aiohttp
721
+ async with aiohttp.ClientSession() as session:
722
+ try:
723
+ async with session.get(http_config['url']) as response:
724
+ print(f"HTTP status: {response.status}")
725
+ except Exception as http_error:
726
+ print(f"HTTP test failed: {http_error}")
727
+ ```
728
+
729
+ #### Server Errors
730
+
731
+ **Symptoms:**
732
+ - `MCPServerError` with server error codes
733
+ - Tool execution failures
734
+
735
+ **Common Causes:**
736
+ 1. Invalid tool arguments
737
+ 2. Server-side bugs or crashes
738
+ 3. Resource access issues
739
+ 4. Permission problems
740
+
741
+ **Resolution Steps:**
742
+ ```python
743
+ try:
744
+ result = await client.call_tool("problematic_tool", args)
745
+ except MCPServerError as e:
746
+ print(f"Server error code: {e.code}")
747
+ print(f"HTTP status: {e.http_status}")
748
+ print(f"Response data: {e.response_data}")
749
+
750
+ # Check for specific error patterns
751
+ if e.code == -32602: # Invalid params
752
+ print("Check tool arguments format")
753
+ elif e.code == -32601: # Method not found
754
+ print("Tool may not be available on this server")
755
+ elif e.http_status == 500:
756
+ print("Internal server error - check server logs")
757
+ ```
758
+
759
+ #### Timeout Issues
760
+
761
+ **Symptoms:**
762
+ - `MCPTimeoutError` with timing information
763
+ - Operations hanging or taking too long
764
+
765
+ **Common Causes:**
766
+ 1. Network latency
767
+ 2. Server overload
768
+ 3. Large data processing
769
+ 4. Insufficient timeout values
770
+
771
+ **Resolution Steps:**
772
+ ```python
773
+ try:
774
+ result = await client.call_tool("slow_tool", args)
775
+ except MCPTimeoutError as e:
776
+ print(f"Timeout: {e.timeout_seconds}s, Elapsed: {e.elapsed_seconds}s")
777
+
778
+ # Adjust timeout for slow operations
779
+ client.timeout_seconds = 60 # Increase timeout
780
+
781
+ # Or implement chunked processing
782
+ if "large_file" in args:
783
+ # Process in smaller chunks
784
+ pass
785
+ ```
786
+
787
+ #### Configuration Issues
788
+
789
+ **Symptoms:**
790
+ - `MCPConfigurationError` or `MCPValidationError`
791
+ - Missing or invalid configuration values
792
+
793
+ **Common Causes:**
794
+ 1. Missing required configuration keys
795
+ 2. Invalid data types
796
+ 3. Malformed YAML/JSON
797
+ 4. Environment variable issues
798
+
799
+ **Resolution Steps:**
800
+ ```python
801
+ try:
802
+ config = MCPConfigValidator.validate_server_config(raw_config)
803
+ except MCPConfigurationError as e:
804
+ print(f"Configuration error: {e}")
805
+
806
+ if e.missing_keys:
807
+ print(f"Add missing keys: {e.missing_keys}")
808
+
809
+ if e.config_file:
810
+ print(f"Check file: {e.config_file}")
811
+
812
+ # Show expected format
813
+ example_config = {
814
+ "name": "server-name",
815
+ "type": "stdio",
816
+ "command": "python",
817
+ "args": ["-m", "server_module"]
818
+ }
819
+ print(f"Expected format: {example_config}")
820
+ ```
821
+
822
+ ### Error Pattern Analysis
823
+
824
+ #### Analyzing Error Chains
825
+
826
+ ```python
827
+ from massgen.mcp_tools.exceptions import format_error_chain
828
+
829
+ def analyze_error_chain(exception):
830
+ """Analyze and report on exception chains."""
831
+
832
+ chain = format_error_chain(exception)
833
+ print(f"Error chain: {chain}")
834
+
835
+ # Extract root cause
836
+ current = exception
837
+ while current.__cause__ or current.__context__:
838
+ current = current.__cause__ or current.__context__
839
+
840
+ print(f"Root cause: {type(current).__name__}: {current}")
841
+
842
+ # Check for common patterns
843
+ if "ConnectionRefusedError" in chain:
844
+ print("Suggestion: Check if server is running and port is correct")
845
+ elif "TimeoutError" in chain:
846
+ print("Suggestion: Increase timeout or check network connectivity")
847
+ elif "PermissionError" in chain:
848
+ print("Suggestion: Check file permissions or authentication")
849
+ ```
850
+
851
+ #### Error Frequency Analysis
852
+
853
+ ```python
854
+ from collections import defaultdict
855
+ from massgen.mcp_tools.exceptions import MCPError
856
+
857
+ class ErrorAnalyzer:
858
+ """Analyze error patterns for debugging."""
859
+
860
+ def __init__(self):
861
+ self.error_counts = defaultdict(int)
862
+ self.error_contexts = []
863
+
864
+ def record_error(self, error: MCPError):
865
+ """Record error for analysis."""
866
+ error_type = type(error).__name__
867
+ self.error_counts[error_type] += 1
868
+ self.error_contexts.append(error.to_dict())
869
+
870
+ def get_summary(self):
871
+ """Get error summary."""
872
+ total_errors = sum(self.error_counts.values())
873
+
874
+ summary = {
875
+ "total_errors": total_errors,
876
+ "error_types": dict(self.error_counts),
877
+ "most_common": max(self.error_counts.items(), key=lambda x: x[1]) if self.error_counts else None
878
+ }
879
+
880
+ return summary
881
+
882
+ def get_server_errors(self):
883
+ """Get errors by server."""
884
+ server_errors = defaultdict(int)
885
+
886
+ for context in self.error_contexts:
887
+ server_name = context.get("context", {}).get("server_name")
888
+ if server_name:
889
+ server_errors[server_name] += 1
890
+
891
+ return dict(server_errors)
892
+
893
+ # Usage
894
+ analyzer = ErrorAnalyzer()
895
+
896
+ try:
897
+ # MCP operations
898
+ pass
899
+ except MCPError as e:
900
+ analyzer.record_error(e)
901
+
902
+ # Analyze patterns
903
+ summary = analyzer.get_summary()
904
+ print(f"Error summary: {summary}")
905
+
906
+ server_errors = analyzer.get_server_errors()
907
+ print(f"Errors by server: {server_errors}")
908
+ ```
909
+
910
+ ## Best Practices
911
+
912
+ ### Error Handling in Async Contexts
913
+
914
+ ```python
915
+ import asyncio
916
+ from massgen.mcp_tools.exceptions import MCPError, MCPTimeoutError
917
+
918
+ async def robust_async_operation():
919
+ """Best practices for async error handling."""
920
+
921
+ tasks = []
922
+
923
+ try:
924
+ # Create multiple tasks
925
+ for i in range(5):
926
+ task = asyncio.create_task(some_mcp_operation(i))
927
+ tasks.append(task)
928
+
929
+ # Wait for all tasks with timeout
930
+ results = await asyncio.wait_for(
931
+ asyncio.gather(*tasks, return_exceptions=True),
932
+ timeout=30.0
933
+ )
934
+
935
+ # Process results and handle exceptions
936
+ for i, result in enumerate(results):
937
+ if isinstance(result, MCPError):
938
+ print(f"Task {i} failed: {result}")
939
+ result.log_error()
940
+ elif isinstance(result, Exception):
941
+ print(f"Task {i} unexpected error: {result}")
942
+ else:
943
+ print(f"Task {i} succeeded: {result}")
944
+
945
+ except asyncio.TimeoutError:
946
+ # Cancel remaining tasks
947
+ for task in tasks:
948
+ if not task.done():
949
+ task.cancel()
950
+
951
+ # Wait for cancellation
952
+ await asyncio.gather(*tasks, return_exceptions=True)
953
+
954
+ raise MCPTimeoutError(
955
+ "Batch operation timed out",
956
+ timeout_seconds=30.0,
957
+ operation="batch_mcp_operations"
958
+ )
959
+
960
+ except Exception as e:
961
+ # Handle unexpected errors
962
+ print(f"Unexpected error in async operation: {e}")
963
+ raise
964
+ ```
965
+
966
+ ### Logging Configuration
967
+
968
+ ```python
969
+ import logging
970
+ import json
971
+ from datetime import datetime
972
+
973
+ # Configure structured logging for MCP errors
974
+ def setup_mcp_logging():
975
+ """Set up logging configuration for MCP operations."""
976
+
977
+ # Create formatter for structured logs
978
+ class MCPFormatter(logging.Formatter):
979
+ def format(self, record):
980
+ log_entry = {
981
+ 'timestamp': datetime.utcnow().isoformat(),
982
+ 'level': record.levelname,
983
+ 'logger': record.name,
984
+ 'message': record.getMessage(),
985
+ }
986
+
987
+ # Add MCP error context if present
988
+ if hasattr(record, 'mcp_error'):
989
+ log_entry['mcp_error'] = record.mcp_error
990
+
991
+ # Add exception info if present
992
+ if record.exc_info:
993
+ log_entry['exception'] = self.formatException(record.exc_info)
994
+
995
+ return json.dumps(log_entry)
996
+
997
+ # Set up handler
998
+ handler = logging.StreamHandler()
999
+ handler.setFormatter(MCPFormatter())
1000
+
1001
+ # Configure MCP logger
1002
+ mcp_logger = logging.getLogger('massgen.mcp_tools')
1003
+ mcp_logger.setLevel(logging.INFO)
1004
+ mcp_logger.addHandler(handler)
1005
+
1006
+ return mcp_logger
1007
+
1008
+ # Usage
1009
+ logger = setup_mcp_logging()
1010
+
1011
+ try:
1012
+ # MCP operations
1013
+ pass
1014
+ except MCPError as e:
1015
+ e.log_error(logger)
1016
+ ```
1017
+
1018
+ ### Error Propagation Patterns
1019
+
1020
+ ```python
1021
+ from massgen.mcp_tools.exceptions import MCPError, MCPConnectionError
1022
+
1023
+ class MCPService:
1024
+ """Service class demonstrating error propagation patterns."""
1025
+
1026
+ def __init__(self, client):
1027
+ self.client = client
1028
+
1029
+ async def high_level_operation(self, data):
1030
+ """High-level operation that may fail."""
1031
+ try:
1032
+ return await self._process_data(data)
1033
+ except MCPError as e:
1034
+ # Add service-level context
1035
+ e.context = e.context or {}
1036
+ e.context.update({
1037
+ 'service': 'MCPService',
1038
+ 'operation': 'high_level_operation',
1039
+ 'data_size': len(str(data))
1040
+ })
1041
+
1042
+ # Re-raise with additional context
1043
+ raise
1044
+
1045
+ async def _process_data(self, data):
1046
+ """Internal processing that may fail."""
1047
+ try:
1048
+ return await self.client.call_tool("process", {"data": data})
1049
+ except MCPConnectionError as e:
1050
+ # Convert to service-specific error
1051
+ raise MCPError(
1052
+ f"Service unavailable: {e.original_message}",
1053
+ context={
1054
+ 'service_operation': 'data_processing',
1055
+ 'original_error': e.to_dict()
1056
+ },
1057
+ error_code="SERVICE_UNAVAILABLE"
1058
+ ) from e
1059
+
1060
+ # Usage with proper error handling
1061
+ service = MCPService(client)
1062
+
1063
+ try:
1064
+ result = await service.high_level_operation({"key": "value"})
1065
+ except MCPError as e:
1066
+ # Handle service-level errors
1067
+ print(f"Service error: {e}")
1068
+
1069
+ # Check for specific error codes
1070
+ if e.error_code == "SERVICE_UNAVAILABLE":
1071
+ print("Service is temporarily unavailable")
1072
+
1073
+ # Log with full context
1074
+ e.log_error()
1075
+ ```
1076
+
1077
+ ### Testing Error Conditions
1078
+
1079
+ ```python
1080
+ import pytest
1081
+ from unittest.mock import AsyncMock, patch
1082
+ from massgen.mcp_tools.exceptions import MCPConnectionError, MCPTimeoutError
1083
+
1084
+ class TestMCPErrorHandling:
1085
+ """Test cases for MCP error handling."""
1086
+
1087
+ @pytest.mark.asyncio
1088
+ async def test_connection_error_handling(self):
1089
+ """Test connection error scenarios."""
1090
+
1091
+ # Mock client that raises connection error
1092
+ mock_client = AsyncMock()
1093
+ mock_client.call_tool.side_effect = MCPConnectionError(
1094
+ "Connection failed",
1095
+ server_name="test-server",
1096
+ transport_type="stdio"
1097
+ )
1098
+
1099
+ # Test error handling
1100
+ with pytest.raises(MCPConnectionError) as exc_info:
1101
+ await mock_client.call_tool("test_tool", {})
1102
+
1103
+ error = exc_info.value
1104
+ assert error.server_name == "test-server"
1105
+ assert error.transport_type == "stdio"
1106
+ assert "Connection failed" in str(error)
1107
+
1108
+ @pytest.mark.asyncio
1109
+ async def test_timeout_error_handling(self):
1110
+ """Test timeout error scenarios."""
1111
+
1112
+ mock_client = AsyncMock()
1113
+ mock_client.call_tool.side_effect = MCPTimeoutError(
1114
+ "Operation timed out",
1115
+ timeout_seconds=30.0,
1116
+ operation="call_tool",
1117
+ elapsed_seconds=30.5
1118
+ )
1119
+
1120
+ with pytest.raises(MCPTimeoutError) as exc_info:
1121
+ await mock_client.call_tool("slow_tool", {})
1122
+
1123
+ error = exc_info.value
1124
+ assert error.timeout_seconds == 30.0
1125
+ assert error.elapsed_seconds == 30.5
1126
+ assert error.operation == "call_tool"
1127
+
1128
+ def test_error_sanitization(self):
1129
+ """Test that sensitive data is properly sanitized."""
1130
+
1131
+ error = MCPConnectionError(
1132
+ "Auth failed",
1133
+ context={
1134
+ "username": "test_user",
1135
+ "password": "secret123",
1136
+ "api_key": "sk-abcdef",
1137
+ "server": "api.example.com"
1138
+ }
1139
+ )
1140
+
1141
+ # Check sanitization
1142
+ assert error.context["username"] == "test_user"
1143
+ assert error.context["password"] == "[REDACTED]"
1144
+ assert error.context["api_key"] == "[REDACTED]"
1145
+ assert error.context["server"] == "api.example.com"
1146
+
1147
+ def test_error_serialization(self):
1148
+ """Test error serialization to dict."""
1149
+
1150
+ error = MCPConnectionError(
1151
+ "Test error",
1152
+ server_name="test-server",
1153
+ error_code="TEST_ERROR"
1154
+ )
1155
+
1156
+ error_dict = error.to_dict()
1157
+
1158
+ assert error_dict["error_type"] == "MCPConnectionError"
1159
+ assert error_dict["message"] == "Test error"
1160
+ assert error_dict["error_code"] == "TEST_ERROR"
1161
+ assert "timestamp" in error_dict
1162
+ assert "context" in error_dict
1163
+ ```
1164
+
1165
+ This comprehensive documentation provides developers with everything they need to effectively handle errors in MCP integrations, from basic exception handling to advanced error analysis and recovery patterns.