hanzo-mcp 0.6.9__tar.gz → 0.6.12__tar.gz

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 hanzo-mcp might be problematic. Click here for more details.

Files changed (157) hide show
  1. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/PKG-INFO +3 -1
  2. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/README.md +2 -0
  3. hanzo_mcp-0.6.12/hanzo_mcp/__init__.py +12 -0
  4. hanzo_mcp-0.6.12/hanzo_mcp/__main__.py +6 -0
  5. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/cli.py +69 -31
  6. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/cli_enhanced.py +12 -9
  7. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/config/settings.py +6 -2
  8. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/dev_server.py +18 -13
  9. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/server.py +13 -9
  10. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/__init__.py +3 -1
  11. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/agent/agent.py +5 -1
  12. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/agent/agent_tool.py +5 -1
  13. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/agent/tool_adapter.py +6 -1
  14. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/bash_session_executor.py +7 -4
  15. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/command_executor.py +6 -4
  16. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/__init__.py +6 -2
  17. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/ast_analyzer.py +12 -4
  18. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/infinity_store.py +9 -3
  19. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/project_manager.py +3 -1
  20. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp.egg-info/PKG-INFO +3 -1
  21. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp.egg-info/SOURCES.txt +6 -1
  22. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp.egg-info/entry_points.txt +1 -1
  23. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/pyproject.toml +2 -2
  24. hanzo_mcp-0.6.12/tests/test_litellm_warnings.py +72 -0
  25. hanzo_mcp-0.6.12/tests/test_manual.py +188 -0
  26. hanzo_mcp-0.6.12/tests/test_palette.py +35 -0
  27. hanzo_mcp-0.6.12/tests/test_simple.py +253 -0
  28. hanzo_mcp-0.6.12/tests/test_stdio_protocol.py +164 -0
  29. hanzo_mcp-0.6.12/tests/test_stdio_simple.py +91 -0
  30. hanzo_mcp-0.6.9/hanzo_mcp/__init__.py +0 -3
  31. hanzo_mcp-0.6.9/hanzo_mcp/__main__.py +0 -17
  32. hanzo_mcp-0.6.9/hanzo_mcp/entry.py +0 -33
  33. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/LICENSE +0 -0
  34. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/config/__init__.py +0 -0
  35. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/config/tool_config.py +0 -0
  36. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/prompts/__init__.py +0 -0
  37. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/prompts/compact_conversation.py +0 -0
  38. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/prompts/create_release.py +0 -0
  39. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/prompts/project_system.py +0 -0
  40. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/prompts/project_todo_reminder.py +0 -0
  41. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/prompts/utils.py +0 -0
  42. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/agent/__init__.py +0 -0
  43. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/agent/prompt.py +0 -0
  44. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/__init__.py +0 -0
  45. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/base.py +0 -0
  46. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/batch_tool.py +0 -0
  47. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/config_tool.py +0 -0
  48. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/context.py +0 -0
  49. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/palette.py +0 -0
  50. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/palette_loader.py +0 -0
  51. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/permissions.py +0 -0
  52. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/stats.py +0 -0
  53. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/thinking_tool.py +0 -0
  54. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/tool_disable.py +0 -0
  55. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/tool_enable.py +0 -0
  56. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/tool_list.py +0 -0
  57. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/common/validation.py +0 -0
  58. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/config/__init__.py +0 -0
  59. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/config/config_tool.py +0 -0
  60. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/config/index_config.py +0 -0
  61. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/config/palette_tool.py +0 -0
  62. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/__init__.py +0 -0
  63. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/database_manager.py +0 -0
  64. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/graph.py +0 -0
  65. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/graph_add.py +0 -0
  66. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/graph_query.py +0 -0
  67. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/graph_remove.py +0 -0
  68. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/graph_search.py +0 -0
  69. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/graph_stats.py +0 -0
  70. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/sql.py +0 -0
  71. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/sql_query.py +0 -0
  72. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/sql_search.py +0 -0
  73. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/database/sql_stats.py +0 -0
  74. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/editor/__init__.py +0 -0
  75. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/editor/neovim_command.py +0 -0
  76. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/editor/neovim_edit.py +0 -0
  77. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/editor/neovim_session.py +0 -0
  78. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/__init__.py +0 -0
  79. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/base.py +0 -0
  80. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/batch_search.py +0 -0
  81. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/content_replace.py +0 -0
  82. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/diff.py +0 -0
  83. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/directory_tree.py +0 -0
  84. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/edit.py +0 -0
  85. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/find.py +0 -0
  86. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/find_files.py +0 -0
  87. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/git_search.py +0 -0
  88. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/grep.py +0 -0
  89. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/multi_edit.py +0 -0
  90. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/read.py +0 -0
  91. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/symbols.py +0 -0
  92. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/symbols_unified.py +0 -0
  93. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/tree.py +0 -0
  94. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/unified_search.py +0 -0
  95. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/unix_aliases.py +0 -0
  96. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/watch.py +0 -0
  97. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/filesystem/write.py +0 -0
  98. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/jupyter/__init__.py +0 -0
  99. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/jupyter/base.py +0 -0
  100. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/jupyter/jupyter.py +0 -0
  101. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/jupyter/notebook_edit.py +0 -0
  102. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/jupyter/notebook_read.py +0 -0
  103. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/llm/__init__.py +0 -0
  104. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/llm/consensus_tool.py +0 -0
  105. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/llm/llm_manage.py +0 -0
  106. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/llm/llm_tool.py +0 -0
  107. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/llm/llm_unified.py +0 -0
  108. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/llm/provider_tools.py +0 -0
  109. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/mcp/__init__.py +0 -0
  110. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/mcp/mcp_add.py +0 -0
  111. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/mcp/mcp_remove.py +0 -0
  112. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/mcp/mcp_stats.py +0 -0
  113. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/mcp/mcp_unified.py +0 -0
  114. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/__init__.py +0 -0
  115. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/base.py +0 -0
  116. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/base_process.py +0 -0
  117. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/bash_session.py +0 -0
  118. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/bash_unified.py +0 -0
  119. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/logs.py +0 -0
  120. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/npx.py +0 -0
  121. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/npx_background.py +0 -0
  122. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/npx_unified.py +0 -0
  123. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/open.py +0 -0
  124. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/pkill.py +0 -0
  125. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/process_unified.py +0 -0
  126. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/processes.py +0 -0
  127. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/run_background.py +0 -0
  128. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/run_command.py +0 -0
  129. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/run_command_windows.py +0 -0
  130. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/session_manager.py +0 -0
  131. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/session_storage.py +0 -0
  132. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/uvx.py +0 -0
  133. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/uvx_background.py +0 -0
  134. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/shell/uvx_unified.py +0 -0
  135. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/todo/__init__.py +0 -0
  136. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/todo/base.py +0 -0
  137. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/todo/todo.py +0 -0
  138. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/todo/todo_read.py +0 -0
  139. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/todo/todo_write.py +0 -0
  140. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/git_ingester.py +0 -0
  141. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/index_tool.py +0 -0
  142. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/mock_infinity.py +0 -0
  143. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/vector.py +0 -0
  144. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/vector_index.py +0 -0
  145. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp/tools/vector/vector_search.py +0 -0
  146. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp.egg-info/dependency_links.txt +0 -0
  147. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp.egg-info/requires.txt +0 -0
  148. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/hanzo_mcp.egg-info/top_level.txt +0 -0
  149. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/setup.cfg +0 -0
  150. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/setup.py +0 -0
  151. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/tests/test_async_support.py +0 -0
  152. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/tests/test_cli.py +0 -0
  153. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/tests/test_git_ingestion.py +0 -0
  154. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/tests/test_new_tools.py +0 -0
  155. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/tests/test_search_quality.py +0 -0
  156. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/tests/test_unified_search.py +0 -0
  157. {hanzo_mcp-0.6.9 → hanzo_mcp-0.6.12}/tests/test_vector_store.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hanzo-mcp
3
- Version: 0.6.9
3
+ Version: 0.6.12
4
4
  Summary: The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others.
5
5
  Author-email: Hanzo Industries Inc <dev@hanzo.ai>
6
6
  License: MIT
@@ -76,6 +76,8 @@ Hanzo MCP isn't just another Model Context Protocol server—it's **THE** MCP se
76
76
  uvx hanzo-mcp
77
77
  ```
78
78
 
79
+ > **Note on Deprecation Warnings**: If you see Pydantic deprecation warnings, clear your uvx cache with `rm -rf ~/.cache/uv/` and run again. This is due to litellm using old Pydantic v1 config style in cached environments.
80
+
79
81
  ## 🎯 Why Hanzo MCP?
80
82
 
81
83
  ### The Problem with Other MCPs
@@ -16,6 +16,8 @@ Hanzo MCP isn't just another Model Context Protocol server—it's **THE** MCP se
16
16
  uvx hanzo-mcp
17
17
  ```
18
18
 
19
+ > **Note on Deprecation Warnings**: If you see Pydantic deprecation warnings, clear your uvx cache with `rm -rf ~/.cache/uv/` and run again. This is due to litellm using old Pydantic v1 config style in cached environments.
20
+
19
21
  ## 🎯 Why Hanzo MCP?
20
22
 
21
23
  ### The Problem with Other MCPs
@@ -0,0 +1,12 @@
1
+ """Hanzo MCP - Implementation of Hanzo capabilities using MCP."""
2
+
3
+ # Configure FastMCP logging globally for stdio transport
4
+ import os
5
+ if os.environ.get("HANZO_MCP_TRANSPORT") == "stdio":
6
+ try:
7
+ from fastmcp.utilities.logging import configure_logging
8
+ configure_logging(level="ERROR")
9
+ except ImportError:
10
+ pass
11
+
12
+ __version__ = "0.6.12"
@@ -0,0 +1,6 @@
1
+ """Main entry point for hanzo-mcp when run as a module."""
2
+
3
+ from hanzo_mcp.cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -1,37 +1,46 @@
1
1
  """Command-line interface for the Hanzo MCP server."""
2
2
 
3
- # CRITICAL: Suppress warnings BEFORE any imports that might trigger them
4
- import warnings
5
- import os
6
- import sys
7
-
8
- # Set environment variable to suppress warnings in subprocesses
9
- os.environ["PYTHONWARNINGS"] = "ignore::DeprecationWarning"
10
-
11
- # Suppress ALL deprecation warnings
12
- warnings.simplefilter("ignore", DeprecationWarning)
13
- warnings.filterwarnings("ignore", category=DeprecationWarning)
14
-
15
- # Now safe to import everything else
16
3
  import argparse
17
4
  import json
5
+ import logging
6
+ import os
18
7
  import signal
8
+ import sys
19
9
  from pathlib import Path
20
10
  from typing import Any, cast
21
11
 
22
- # Import server AFTER warning suppression
23
12
  from hanzo_mcp.server import HanzoMCPServer
24
13
 
25
14
 
26
15
  def main() -> None:
27
16
  """Run the CLI for the Hanzo MCP server."""
28
- # Set up signal handler to ensure clean exit
29
- def signal_handler(signum, frame):
30
- print("\nReceived interrupt signal, shutting down...")
31
- sys.exit(0)
32
17
 
33
- signal.signal(signal.SIGINT, signal_handler)
34
- signal.signal(signal.SIGTERM, signal_handler)
18
+ # Pre-parse arguments to check transport type early
19
+ import sys
20
+ early_parser = argparse.ArgumentParser(add_help=False)
21
+ early_parser.add_argument("--transport", choices=["stdio", "sse"], default="stdio")
22
+ early_args, _ = early_parser.parse_known_args()
23
+
24
+ # Configure logging VERY early based on transport
25
+ if early_args.transport == "stdio":
26
+ # Set environment variable for server to detect stdio mode
27
+ import os
28
+ os.environ["HANZO_MCP_TRANSPORT"] = "stdio"
29
+
30
+ # For stdio transport, disable ALL logging immediately
31
+ from fastmcp.utilities.logging import configure_logging
32
+ # Set to ERROR to suppress INFO/WARNING messages from FastMCP
33
+ configure_logging(level="ERROR")
34
+
35
+ # Also configure standard logging to ERROR level
36
+ logging.basicConfig(
37
+ level=logging.ERROR, # Only show errors
38
+ handlers=[] # No handlers for stdio to prevent protocol corruption
39
+ )
40
+
41
+ # Redirect stderr to devnull for stdio transport to prevent any output
42
+ import sys
43
+ sys.stderr = open(os.devnull, 'w')
35
44
 
36
45
  parser = argparse.ArgumentParser(
37
46
  description="MCP server implementing Hanzo AI capabilities"
@@ -224,6 +233,32 @@ def main() -> None:
224
233
  )
225
234
  return
226
235
 
236
+ # Get logger
237
+ logger = logging.getLogger(__name__)
238
+
239
+ # Set up signal handler to ensure clean exit
240
+ def signal_handler(signum, frame):
241
+ if transport != "stdio":
242
+ logger.info("\nReceived interrupt signal, shutting down...")
243
+ sys.exit(0)
244
+
245
+ signal.signal(signal.SIGINT, signal_handler)
246
+ signal.signal(signal.SIGTERM, signal_handler)
247
+
248
+ # Configure logging based on transport (stdio already configured early)
249
+ if transport != "stdio":
250
+ # For SSE transport, logging is fine
251
+ log_level_map = {
252
+ "DEBUG": logging.DEBUG,
253
+ "INFO": logging.INFO,
254
+ "WARNING": logging.WARNING,
255
+ "ERROR": logging.ERROR
256
+ }
257
+ logging.basicConfig(
258
+ level=log_level_map.get(log_level, logging.INFO),
259
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
260
+ )
261
+
227
262
  # If no allowed paths are specified, use the current directory
228
263
  if not allowed_paths:
229
264
  allowed_paths = [os.getcwd()]
@@ -275,10 +310,11 @@ def main() -> None:
275
310
  # Transport will be automatically cast to Literal['stdio', 'sse'] by the server
276
311
  server.run(transport=transport)
277
312
  except KeyboardInterrupt:
278
- print("\nShutting down...")
313
+ if transport != "stdio":
314
+ logger.info("\nShutting down...")
279
315
  sys.exit(0)
280
316
  except Exception as e:
281
- print(f"Server error: {e}", file=sys.stderr)
317
+ logger.error(f"Server error: {e}")
282
318
  sys.exit(1)
283
319
 
284
320
 
@@ -354,27 +390,29 @@ def install_claude_desktop_config(
354
390
  existing_config["mcpServers"][name] = config["mcpServers"][name]
355
391
  config = existing_config
356
392
  except Exception as e:
357
- print(f"Error reading existing config: {e}")
358
- print("Creating new config file.")
393
+ logger = logging.getLogger(__name__)
394
+ logger.error(f"Error reading existing config: {e}")
395
+ logger.info("Creating new config file.")
359
396
 
360
397
  # Write the config file
361
398
  with open(config_file, mode="w") as f:
362
399
  json.dump(config, f, indent=2)
363
400
 
364
- print(f"Successfully installed {name} in Claude Desktop configuration.")
365
- print(f"Config file: {config_file}")
401
+ logger = logging.getLogger(__name__)
402
+ logger.info(f"Successfully installed {name} in Claude Desktop configuration.")
403
+ logger.info(f"Config file: {config_file}")
366
404
 
367
405
  if allowed_paths:
368
- print("\nAllowed paths:")
406
+ logger.info("\nAllowed paths:")
369
407
  for path in allowed_paths:
370
- print(f"- {path}")
408
+ logger.info(f"- {path}")
371
409
  else:
372
- print(f"\nDefault allowed path: {home}")
410
+ logger.info(f"\nDefault allowed path: {home}")
373
411
 
374
- print(
412
+ logger.info(
375
413
  "\nYou can modify allowed paths in the config file directly."
376
414
  )
377
- print("Restart Claude Desktop for changes to take effect.")
415
+ logger.info("Restart Claude Desktop for changes to take effect.")
378
416
 
379
417
 
380
418
  if __name__ == "__main__":
@@ -2,6 +2,7 @@
2
2
 
3
3
  import argparse
4
4
  import json
5
+ import logging
5
6
  import os
6
7
  import sys
7
8
  from pathlib import Path
@@ -344,8 +345,9 @@ def apply_cli_overrides(args: argparse.Namespace) -> Dict[str, Any]:
344
345
 
345
346
  def list_tools(settings: HanzoMCPSettings) -> None:
346
347
  """List all tools and their current status."""
347
- print("Hanzo MCP Tools Status:")
348
- print("=" * 50)
348
+ logger = logging.getLogger(__name__)
349
+ logger.info("Hanzo MCP Tools Status:")
350
+ logger.info("=" * 50)
349
351
 
350
352
  categories = {}
351
353
  for tool_name, tool_config in TOOL_REGISTRY.items():
@@ -358,14 +360,14 @@ def list_tools(settings: HanzoMCPSettings) -> None:
358
360
  categories[category].append((tool_name, status, tool_config.description))
359
361
 
360
362
  for category, tools in categories.items():
361
- print(f"\n{category.upper()} TOOLS:")
362
- print("-" * 30)
363
+ logger.info(f"\n{category.upper()} TOOLS:")
364
+ logger.info("-" * 30)
363
365
  for tool_name, status, description in tools:
364
- print(f" {status} {tool_name:<15} - {description}")
366
+ logger.info(f" {status} {tool_name:<15} - {description}")
365
367
 
366
- print(f"\nTotal: {len(TOOL_REGISTRY)} tools")
368
+ logger.info(f"\nTotal: {len(TOOL_REGISTRY)} tools")
367
369
  enabled_count = len(settings.get_enabled_tools())
368
- print(f"Enabled: {enabled_count}, Disabled: {len(TOOL_REGISTRY) - enabled_count}")
370
+ logger.info(f"Enabled: {enabled_count}, Disabled: {len(TOOL_REGISTRY) - enabled_count}")
369
371
 
370
372
 
371
373
  def main() -> None:
@@ -385,14 +387,15 @@ def main() -> None:
385
387
  settings = load_settings(project_dir=project_dir, config_overrides=config_overrides)
386
388
 
387
389
  # Handle configuration saving
390
+ logger = logging.getLogger(__name__)
388
391
  if hasattr(args, 'save_config') and args.save_config:
389
392
  saved_path = save_settings(settings, global_config=True)
390
- print(f"Configuration saved to: {saved_path}")
393
+ logger.info(f"Configuration saved to: {saved_path}")
391
394
  return
392
395
 
393
396
  if hasattr(args, 'save_project_config') and args.save_project_config:
394
397
  saved_path = save_settings(settings, global_config=False)
395
- print(f"Project configuration saved to: {saved_path}")
398
+ logger.info(f"Project configuration saved to: {saved_path}")
396
399
  return
397
400
 
398
401
  # Handle installation
@@ -364,7 +364,9 @@ def load_settings(
364
364
  global_config = json.load(f)
365
365
  settings = _merge_config(settings, global_config)
366
366
  except Exception as e:
367
- print(f"Warning: Failed to load global config: {e}")
367
+ import logging
368
+ logger = logging.getLogger(__name__)
369
+ logger.warning(f"Failed to load global config: {e}")
368
370
 
369
371
  # Load project config
370
372
  project_config_path = get_project_config_path(project_dir)
@@ -374,7 +376,9 @@ def load_settings(
374
376
  project_config = json.load(f)
375
377
  settings = _merge_config(settings, project_config)
376
378
  except Exception as e:
377
- print(f"Warning: Failed to load project config: {e}")
379
+ import logging
380
+ logger = logging.getLogger(__name__)
381
+ logger.warning(f"Failed to load project config: {e}")
378
382
 
379
383
  # Apply CLI overrides
380
384
  if config_overrides:
@@ -1,6 +1,7 @@
1
1
  """Development server with hot reload for Hanzo MCP."""
2
2
 
3
3
  import asyncio
4
+ import logging
4
5
  import os
5
6
  import sys
6
7
  import time
@@ -67,8 +68,9 @@ class MCPReloadHandler(FileSystemEventHandler):
67
68
 
68
69
  self.last_reload = current_time
69
70
 
70
- print(f"\n🔄 File changed: {event.src_path}")
71
- print("🔄 Reloading MCP server...")
71
+ logger = logging.getLogger(__name__)
72
+ logger.info(f"\n🔄 File changed: {event.src_path}")
73
+ logger.info("🔄 Reloading MCP server...")
72
74
 
73
75
  self.restart_callback()
74
76
 
@@ -133,9 +135,10 @@ class DevServer:
133
135
  self.observer.schedule(handler, path, recursive=True)
134
136
 
135
137
  self.observer.start()
136
- print(f"👀 Watching for changes in: {package_dir}")
138
+ logger = logging.getLogger(__name__)
139
+ logger.info(f"👀 Watching for changes in: {package_dir}")
137
140
  if self.project_dir:
138
- print(f"👀 Also watching: {self.project_dir}")
141
+ logger.info(f"👀 Also watching: {self.project_dir}")
139
142
 
140
143
  def stop_file_watcher(self):
141
144
  """Stop the file watcher."""
@@ -146,18 +149,20 @@ class DevServer:
146
149
  def restart_server(self):
147
150
  """Restart the MCP server."""
148
151
  # Since MCP servers run in the same process, we need to handle this differently
149
- # For now, we'll print a message indicating a restart is needed
150
- print("\n⚠️ Server restart required. Please restart the MCP client to reload changes.")
151
- print("💡 Tip: In development, consider using the MCP test client for easier reloading.")
152
+ # For now, we'll log a message indicating a restart is needed
153
+ logger = logging.getLogger(__name__)
154
+ logger.warning("\n⚠️ Server restart required. Please restart the MCP client to reload changes.")
155
+ logger.info("💡 Tip: In development, consider using the MCP test client for easier reloading.")
152
156
 
153
157
  async def run_async(self, transport: str = "stdio"):
154
158
  """Run the development server asynchronously."""
155
159
  self.running = True
156
160
 
157
- print(f"\n🚀 Starting Hanzo MCP in development mode...")
158
- print(f"🔧 Hot reload enabled - watching for file changes")
159
- print(f"📁 Project: {self.project_dir or 'current directory'}")
160
- print(f"🌐 Transport: {transport}\n")
161
+ logger = logging.getLogger(__name__)
162
+ logger.info(f"\n🚀 Starting Hanzo MCP in development mode...")
163
+ logger.info(f"🔧 Hot reload enabled - watching for file changes")
164
+ logger.info(f"📁 Project: {self.project_dir or 'current directory'}")
165
+ logger.info(f"🌐 Transport: {transport}\n")
161
166
 
162
167
  # Start file watcher
163
168
  self.start_file_watcher()
@@ -170,11 +175,11 @@ class DevServer:
170
175
  server.run(transport=transport)
171
176
 
172
177
  except KeyboardInterrupt:
173
- print("\n\n🛑 Shutting down development server...")
178
+ logger.info("\n\n🛑 Shutting down development server...")
174
179
  finally:
175
180
  self.running = False
176
181
  self.stop_file_watcher()
177
- print("👋 Development server stopped")
182
+ logger.info("👋 Development server stopped")
178
183
 
179
184
  def run(self, transport: str = "stdio"):
180
185
  """Run the development server."""
@@ -1,19 +1,14 @@
1
1
  """MCP server implementing Hanzo capabilities."""
2
2
 
3
3
  import atexit
4
+ import logging
4
5
  import signal
5
6
  import threading
6
7
  import time
7
8
  import warnings
8
9
  from typing import Literal, cast, final
9
10
 
10
- # Suppress deprecation warnings from litellm about Pydantic v1 style configs
11
- warnings.filterwarnings(
12
- "ignore",
13
- category=DeprecationWarning,
14
- message=".*class-based `config`.*",
15
- module="pydantic.*"
16
- )
11
+ # No need for warning suppression here as it's handled in the imports
17
12
 
18
13
  try:
19
14
  from fastmcp import FastMCP
@@ -160,7 +155,10 @@ class HanzoMCPServer:
160
155
  # Register signal handlers for graceful shutdown
161
156
  def signal_handler(signum, frame):
162
157
  import sys
163
- print("\nShutting down gracefully...")
158
+ # Only log if not stdio transport
159
+ if hasattr(self, '_transport') and self._transport != 'stdio':
160
+ logger = logging.getLogger(__name__)
161
+ logger.info("\nShutting down gracefully...")
164
162
  self._cleanup_sessions()
165
163
  self._shutdown_event.set()
166
164
  sys.exit(0)
@@ -195,7 +193,10 @@ class HanzoMCPServer:
195
193
  try:
196
194
  cleared_count = SessionStorage.clear_all_sessions()
197
195
  if cleared_count > 0:
198
- print(f"Cleaned up {cleared_count} tmux sessions on shutdown")
196
+ # Only log if not stdio transport
197
+ if hasattr(self, '_transport') and self._transport != 'stdio':
198
+ logger = logging.getLogger(__name__)
199
+ logger.info(f"Cleaned up {cleared_count} tmux sessions on shutdown")
199
200
  except Exception:
200
201
  # Ignore cleanup errors during shutdown
201
202
  pass
@@ -207,6 +208,9 @@ class HanzoMCPServer:
207
208
  transport: The transport to use (stdio or sse)
208
209
  allowed_paths: list of paths that the server is allowed to access
209
210
  """
211
+ # Store transport for later use
212
+ self._transport = transport
213
+
210
214
  # Add allowed paths if provided
211
215
  allowed_paths_list = allowed_paths or []
212
216
  for path in allowed_paths_list:
@@ -124,7 +124,9 @@ def register_all_tools(
124
124
  )
125
125
  # Auto-detect projects from search paths
126
126
  detected_projects = project_manager.detect_projects(search_paths)
127
- print(f"Detected {len(detected_projects)} projects with LLM.md files")
127
+ import logging
128
+ logger = logging.getLogger(__name__)
129
+ logger.info(f"Detected {len(detected_projects)} projects with LLM.md files")
128
130
 
129
131
  filesystem_tools = register_filesystem_tools(
130
132
  mcp_server,
@@ -12,7 +12,11 @@ import uuid
12
12
  from typing import Annotated, TypedDict, Unpack, final, override, Optional, Dict, Any, List
13
13
  from collections.abc import Iterable
14
14
 
15
- import litellm
15
+ # Import litellm with warnings suppressed
16
+ import warnings
17
+ with warnings.catch_warnings():
18
+ warnings.simplefilter("ignore", DeprecationWarning)
19
+ import litellm
16
20
  from mcp.server.fastmcp import Context as MCPContext
17
21
  from openai.types.chat import ChatCompletionMessageParam, ChatCompletionToolParam
18
22
  from pydantic import Field
@@ -11,7 +11,11 @@ import time
11
11
  from collections.abc import Iterable
12
12
  from typing import Annotated, TypedDict, Unpack, final, override
13
13
 
14
- import litellm
14
+ # Import litellm with warnings suppressed
15
+ import warnings
16
+ with warnings.catch_warnings():
17
+ warnings.simplefilter("ignore", DeprecationWarning)
18
+ import litellm
15
19
  from mcp.server.fastmcp import Context as MCPContext
16
20
  from mcp.server import FastMCP
17
21
  from openai.types.chat import ChatCompletionMessageParam, ChatCompletionToolParam
@@ -7,7 +7,12 @@ and outputs for agent execution.
7
7
 
8
8
  from openai.types import FunctionParameters
9
9
  from openai.types.chat import ChatCompletionToolParam
10
- import litellm
10
+
11
+ # Import litellm with warnings suppressed
12
+ import warnings
13
+ with warnings.catch_warnings():
14
+ warnings.simplefilter("ignore", DeprecationWarning)
15
+ import litellm
11
16
 
12
17
  from hanzo_mcp.tools.common.base import BaseTool
13
18
 
@@ -5,6 +5,7 @@ implementation with the new BashSession-based approach for better persistent exe
5
5
  """
6
6
 
7
7
  import asyncio
8
+ import logging
8
9
  import os
9
10
  import shlex
10
11
  import subprocess
@@ -64,16 +65,18 @@ class BashSessionExecutor:
64
65
  if data is not None:
65
66
  try:
66
67
  import json
67
-
68
+ logger = logging.getLogger(__name__)
68
69
  if isinstance(data, (dict, list)):
69
70
  data_str = json.dumps(data)
70
71
  else:
71
72
  data_str = str(data)
72
- print(f"DEBUG: {message}: {data_str}")
73
+ logger.debug(f"{message}: {data_str}")
73
74
  except Exception:
74
- print(f"DEBUG: {message}: {data}")
75
+ logger = logging.getLogger(__name__)
76
+ logger.debug(f"{message}: {data}")
75
77
  else:
76
- print(f"DEBUG: {message}")
78
+ logger = logging.getLogger(__name__)
79
+ logger.debug(f"{message}")
77
80
 
78
81
  def allow_command(self, command: str) -> None:
79
82
  """Allow a specific command that might otherwise be excluded.
@@ -183,16 +183,18 @@ class CommandExecutor:
183
183
  if data is not None:
184
184
  try:
185
185
  import json
186
-
186
+ logger = logging.getLogger(__name__)
187
187
  if isinstance(data, (dict, list)):
188
188
  data_str = json.dumps(data)
189
189
  else:
190
190
  data_str = str(data)
191
- print(f"DEBUG: {message}: {data_str}", file=sys.stderr)
191
+ logger.debug(f"{message}: {data_str}")
192
192
  except Exception:
193
- print(f"DEBUG: {message}: {data}", file=sys.stderr)
193
+ logger = logging.getLogger(__name__)
194
+ logger.debug(f"{message}: {data}")
194
195
  else:
195
- print(f"DEBUG: {message}", file=sys.stderr)
196
+ logger = logging.getLogger(__name__)
197
+ logger.debug(f"{message}")
196
198
 
197
199
  def is_command_allowed(self, command: str) -> bool:
198
200
  """Check if a command is allowed based on exclusion lists.
@@ -62,7 +62,9 @@ try:
62
62
  # Auto-detect projects from search paths for new manager
63
63
  if search_paths:
64
64
  detected_projects = project_manager.detect_projects(search_paths)
65
- print(f"Detected {len(detected_projects)} projects with LLM.md files")
65
+ import logging
66
+ logger = logging.getLogger(__name__)
67
+ logger.info(f"Detected {len(detected_projects)} projects with LLM.md files")
66
68
 
67
69
  # Register individual tools if enabled
68
70
  if tool_enabled.get("index", True):
@@ -85,7 +87,9 @@ except ImportError:
85
87
 
86
88
  def register_vector_tools(*args, **kwargs) -> list[BaseTool]:
87
89
  """Vector tools not available - missing dependencies."""
88
- print("Warning: Vector tools not available. Install infinity-embedded: pip install infinity-embedded")
90
+ import logging
91
+ logger = logging.getLogger(__name__)
92
+ logger.warning("Vector tools not available. Install infinity-embedded: pip install infinity-embedded")
89
93
  return []
90
94
 
91
95
 
@@ -94,7 +94,9 @@ class ASTAnalyzer:
94
94
  # Python parser
95
95
  self.parsers['python'] = tree_sitter.Language(tspython.language())
96
96
  except Exception as e:
97
- print(f"Warning: Could not initialize Python parser: {e}")
97
+ import logging
98
+ logger = logging.getLogger(__name__)
99
+ logger.warning(f"Could not initialize Python parser: {e}")
98
100
 
99
101
  def analyze_file(self, file_path: str) -> Optional[FileAST]:
100
102
  """Analyze a file and extract AST information and symbols.
@@ -127,7 +129,9 @@ class ASTAnalyzer:
127
129
  return self._analyze_generic_file(file_path, content, file_hash, language)
128
130
 
129
131
  except Exception as e:
130
- print(f"Error analyzing file {file_path}: {e}")
132
+ import logging
133
+ logger = logging.getLogger(__name__)
134
+ logger.error(f"Error analyzing file {file_path}: {e}")
131
135
  return None
132
136
 
133
137
  def _detect_language(self, path: Path) -> Optional[str]:
@@ -194,9 +198,13 @@ class ASTAnalyzer:
194
198
  ast_nodes = self._extract_tree_sitter_nodes(ts_tree.root_node, content)
195
199
 
196
200
  except SyntaxError as e:
197
- print(f"Syntax error in {file_path}: {e}")
201
+ import logging
202
+ logger = logging.getLogger(__name__)
203
+ logger.error(f"Syntax error in {file_path}: {e}")
198
204
  except Exception as e:
199
- print(f"Error parsing Python file {file_path}: {e}")
205
+ import logging
206
+ logger = logging.getLogger(__name__)
207
+ logger.error(f"Error parsing Python file {file_path}: {e}")
200
208
 
201
209
  return FileAST(
202
210
  file_path=file_path,
@@ -528,7 +528,9 @@ class InfinityVectorStore:
528
528
  return file_ast
529
529
 
530
530
  except Exception as e:
531
- print(f"Error searching AST nodes: {e}")
531
+ import logging
532
+ logger = logging.getLogger(__name__)
533
+ logger.error(f"Error searching AST nodes: {e}")
532
534
  return None
533
535
 
534
536
  def get_file_references(self, file_path: str) -> List[Dict[str, Any]]:
@@ -555,7 +557,9 @@ class InfinityVectorStore:
555
557
  return references
556
558
 
557
559
  except Exception as e:
558
- print(f"Error getting file references: {e}")
560
+ import logging
561
+ logger = logging.getLogger(__name__)
562
+ logger.error(f"Error getting file references: {e}")
559
563
  return []
560
564
 
561
565
  def search(
@@ -803,7 +807,9 @@ class InfinityVectorStore:
803
807
 
804
808
  return True
805
809
  except Exception as e:
806
- print(f"Error clearing vector store: {e}")
810
+ import logging
811
+ logger = logging.getLogger(__name__)
812
+ logger.error(f"Error clearing vector store: {e}")
807
813
  return False
808
814
 
809
815
  async def index_document(
@@ -294,7 +294,9 @@ class ProjectVectorManager:
294
294
  project_name = project_names[i]
295
295
  if isinstance(result, Exception):
296
296
  # Log error but continue
297
- print(f"Error searching project {project_name}: {result}")
297
+ import logging
298
+ logger = logging.getLogger(__name__)
299
+ logger.error(f"Error searching project {project_name}: {result}")
298
300
  combined_results[project_name] = []
299
301
  else:
300
302
  combined_results[project_name] = result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hanzo-mcp
3
- Version: 0.6.9
3
+ Version: 0.6.12
4
4
  Summary: The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others.
5
5
  Author-email: Hanzo Industries Inc <dev@hanzo.ai>
6
6
  License: MIT
@@ -76,6 +76,8 @@ Hanzo MCP isn't just another Model Context Protocol server—it's **THE** MCP se
76
76
  uvx hanzo-mcp
77
77
  ```
78
78
 
79
+ > **Note on Deprecation Warnings**: If you see Pydantic deprecation warnings, clear your uvx cache with `rm -rf ~/.cache/uv/` and run again. This is due to litellm using old Pydantic v1 config style in cached environments.
80
+
79
81
  ## 🎯 Why Hanzo MCP?
80
82
 
81
83
  ### The Problem with Other MCPs