hanzo-mcp 0.3.1__py3-none-any.whl → 0.3.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hanzo-mcp might be problematic. Click here for more details.

hanzo_mcp/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Hanzo MCP - Implementation of Hanzo capabilities using MCP."""
2
2
 
3
- __version__ = "0.3.1"
3
+ __version__ = "0.3.3"
hanzo_mcp/cli.py CHANGED
@@ -133,6 +133,14 @@ def main() -> None:
133
133
  default=False,
134
134
  help="Disable logging to file (logs to console only)"
135
135
  )
136
+
137
+ _ = parser.add_argument(
138
+ "--enable-console-logging",
139
+ dest="enable_console_logging",
140
+ action="store_true",
141
+ default=False,
142
+ help="Enable logging to console (stdout/stderr). By default, logs to file only."
143
+ )
136
144
 
137
145
  _ = parser.add_argument(
138
146
  "--disable-write-tools",
@@ -166,13 +174,25 @@ def main() -> None:
166
174
  disable_write_tools: bool = cast(bool, args.disable_write_tools)
167
175
  log_level: str = cast(str, args.log_level)
168
176
  disable_file_logging: bool = cast(bool, args.disable_file_logging)
177
+ enable_console_logging: bool = cast(bool, args.enable_console_logging)
169
178
  allowed_paths: list[str] = (
170
179
  cast(list[str], args.allowed_paths) if args.allowed_paths else []
171
180
  )
172
181
 
173
182
  # Setup logging
174
- setup_logging(log_level=log_level, log_to_file=not disable_file_logging, testing="pytest" in sys.modules)
175
- logger.debug(f"Hanzo MCP CLI started with arguments: {args}")
183
+ # Ensure absolutely NO logging when using stdio transport to avoid protocol corruption
184
+ # For sse transport, use file logging by default and console logging only if explicitly requested
185
+ # Only set up logging if not using stdio transport or explicitly requested
186
+ if transport != "stdio" or (enable_console_logging or not disable_file_logging):
187
+ setup_logging(
188
+ log_level=log_level,
189
+ log_to_file=not disable_file_logging and transport != "stdio", # Disable file logging for stdio transport
190
+ log_to_console=enable_console_logging and transport != "stdio", # Only enable console logging if requested AND not using stdio
191
+ transport=transport, # Pass the transport to ensure it's properly handled
192
+ testing="pytest" in sys.modules
193
+ )
194
+ logger.debug(f"Hanzo MCP CLI started with arguments: {args}")
195
+ # No logging setup at all for stdio transport unless explicitly requested
176
196
 
177
197
 
178
198
  if install:
@@ -200,10 +220,11 @@ def main() -> None:
200
220
  elif allowed_paths:
201
221
  project_dir = allowed_paths[0]
202
222
 
203
- # Run the server
204
- logger.info(f"Starting Hanzo MCP server with name: {name}")
205
- logger.debug(f"Allowed paths: {allowed_paths}")
206
- logger.debug(f"Project directory: {project_dir}")
223
+ # Run the server - only log if not using stdio transport or logging is explicitly enabled
224
+ if transport != "stdio" or (enable_console_logging or not disable_file_logging):
225
+ logger.info(f"Starting Hanzo MCP server with name: {name}")
226
+ logger.debug(f"Allowed paths: {allowed_paths}")
227
+ logger.debug(f"Project directory: {project_dir}")
207
228
 
208
229
  try:
209
230
  server = HanzoServer(
@@ -220,12 +241,19 @@ def main() -> None:
220
241
  host=host,
221
242
  port=port
222
243
  )
223
- logger.info(f"Server initialized successfully, running with transport: {transport}")
244
+
245
+ # Only log if not using stdio transport or logging is explicitly enabled
246
+ if transport != "stdio" or (enable_console_logging or not disable_file_logging):
247
+ logger.info(f"Server initialized successfully, running with transport: {transport}")
248
+
224
249
  # Transport will be automatically cast to Literal['stdio', 'sse'] by the server
225
250
  server.run(transport=transport)
226
251
  except Exception as e:
227
- logger.error(f"Error starting server: {str(e)}")
228
- logger.exception("Server startup failed with exception:")
252
+ # Only log if not using stdio transport or logging is explicitly enabled
253
+ if transport != "stdio" or (enable_console_logging or not disable_file_logging):
254
+ logger.error(f"Error starting server: {str(e)}")
255
+ logger.exception("Server startup failed with exception:")
256
+ # For stdio transport, we want a clean exception without any logging
229
257
  # Re-raise the exception for proper error handling
230
258
  raise
231
259
 
@@ -8,14 +8,23 @@ import os
8
8
  import sys
9
9
  from datetime import datetime
10
10
  from pathlib import Path
11
+ from typing import Optional
11
12
 
12
13
 
13
- def setup_logging(log_level: str = "INFO", log_to_file: bool = True, testing: bool = False) -> None:
14
+ def setup_logging(
15
+ log_level: str = "INFO",
16
+ log_to_file: bool = True,
17
+ log_to_console: bool = False, # Changed default to False
18
+ transport: Optional[str] = None,
19
+ testing: bool = False
20
+ ) -> None:
14
21
  """Set up logging configuration.
15
22
 
16
23
  Args:
17
24
  log_level: The logging level ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")
18
- log_to_file: Whether to log to a file in addition to the console
25
+ log_to_file: Whether to log to a file in addition to the console (default: True)
26
+ log_to_console: Whether to log to the console (default: False to avoid stdio transport conflicts)
27
+ transport: The transport mechanism being used ("stdio" or "sse")
19
28
  testing: Set to True to disable file operations for testing
20
29
  """
21
30
  # Convert string log level to logging constant
@@ -35,12 +44,14 @@ def setup_logging(log_level: str = "INFO", log_to_file: bool = True, testing: bo
35
44
  # Base configuration
36
45
  handlers = []
37
46
 
38
- # Console handler
39
- console = logging.StreamHandler(sys.stdout)
40
- console.setLevel(numeric_level)
41
- console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
42
- console.setFormatter(console_formatter)
43
- handlers.append(console)
47
+ # Console handler - Always use stderr to avoid interfering with stdio transport
48
+ # Disable console logging when using stdio transport to avoid protocol corruption
49
+ if log_to_console and (transport != "stdio"):
50
+ console = logging.StreamHandler(sys.stderr)
51
+ console.setLevel(numeric_level)
52
+ console_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
53
+ console.setFormatter(console_formatter)
54
+ handlers.append(console)
44
55
 
45
56
  # File handler (if enabled)
46
57
  if log_to_file and not testing:
@@ -68,6 +79,8 @@ def setup_logging(log_level: str = "INFO", log_to_file: bool = True, testing: bo
68
79
  root_logger.info(f"Logging initialized at level {log_level}")
69
80
  if log_to_file and not testing:
70
81
  root_logger.info(f"Log file: {log_file}")
82
+ if not log_to_console or transport == "stdio":
83
+ root_logger.info("Console logging disabled")
71
84
 
72
85
 
73
86
  def get_log_files() -> list[str]:
@@ -82,3 +95,21 @@ def get_log_files() -> list[str]:
82
95
 
83
96
  log_files = [str(f) for f in log_dir.glob("hanzo-mcp-*.log")]
84
97
  return sorted(log_files, reverse=True)
98
+
99
+
100
+ def get_current_log_file() -> Optional[str]:
101
+ """Get the path to the current log file.
102
+
103
+ Returns:
104
+ The path to the current log file, or None if no log file exists
105
+ """
106
+ log_dir = Path.home() / ".hanzo" / "logs"
107
+ if not log_dir.exists():
108
+ return None
109
+
110
+ current_time = datetime.now().strftime("%Y-%m-%d")
111
+ log_file = log_dir / f"hanzo-mcp-{current_time}.log"
112
+
113
+ if log_file.exists():
114
+ return str(log_file)
115
+ return None
@@ -155,6 +155,9 @@ class CommandExecutor:
155
155
  Args:
156
156
  message: The message to log
157
157
  data: Optional data to include with the message
158
+
159
+ Note:
160
+ Always logs to stderr to avoid interfering with stdio transport
158
161
  """
159
162
  if not self.verbose:
160
163
  return
@@ -1,12 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hanzo-mcp
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: MCP implementation of Hanzo capabilities
5
5
  Author-email: Hanzo Industries Inc <dev@hanzo.ai>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/hanzoai/mcp
8
8
  Project-URL: Bug Tracker, https://github.com/hanzoai/mcp/issues
9
- Project-URL: Documentation, https://github.com/hanzoai/mcp/blob/main/README.md
9
+ Project-URL: Documentation, https://github.com/hanzoai/mcp/tree/main/docs
10
10
  Keywords: mcp,claude,hanzo,code,agent
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: License :: OSI Approved :: MIT License
@@ -25,6 +25,9 @@ Requires-Dist: pytest>=7.0.0; extra == "dev"
25
25
  Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
26
26
  Requires-Dist: ruff>=0.1.0; extra == "dev"
27
27
  Requires-Dist: black>=23.3.0; extra == "dev"
28
+ Requires-Dist: sphinx>=8.0.0; extra == "dev"
29
+ Requires-Dist: sphinx-rtd-theme>=1.3.0; extra == "dev"
30
+ Requires-Dist: myst-parser>=2.0.0; extra == "dev"
28
31
  Provides-Extra: test
29
32
  Requires-Dist: pytest>=7.0.0; extra == "test"
30
33
  Requires-Dist: pytest-cov>=4.1.0; extra == "test"
@@ -93,7 +96,7 @@ uv pip install hanzo-mcp
93
96
  pip install hanzo-mcp
94
97
  ```
95
98
 
96
- For detailed installation and configuration instructions, please refer to [INSTALL.md](./doc/INSTALL.md).
99
+ For detailed installation and configuration instructions, please refer to the [documentation](./docs/).
97
100
 
98
101
  Of course, you can also read [USEFUL_PROMPTS](./doc/USEFUL_PROMPTS.md) for some inspiration on how to use hanzo-mcp.
99
102
 
@@ -106,6 +109,20 @@ This implementation follows best practices for securing access to your filesyste
106
109
  - Input validation and sanitization
107
110
  - Proper error handling and reporting
108
111
 
112
+ ## Documentation
113
+
114
+ Comprehensive documentation is available in the [docs](./docs/) directory. You can build and view the documentation locally:
115
+
116
+ ```bash
117
+ # Build the documentation
118
+ make docs
119
+
120
+ # Start a local server to view the documentation
121
+ make docs-serve
122
+ ```
123
+
124
+ Then open http://localhost:8000/ in your browser to view the documentation.
125
+
109
126
  ## Development
110
127
 
111
128
  ### Setup Development Environment
@@ -1,5 +1,5 @@
1
- hanzo_mcp/__init__.py,sha256=roRFuV1ugS6Zf28PtFGKzOnpJMDFncOz6fR3TlG-LF0,89
2
- hanzo_mcp/cli.py,sha256=ST428ys32fputErgrmLNJV9oYHbKGwkjrPBJfKh_K_Y,10820
1
+ hanzo_mcp/__init__.py,sha256=TGjXG3-jW-pduEg0z6QzesvTiXw58D44bYgp8m_9qdc,89
2
+ hanzo_mcp/cli.py,sha256=Z_N1ziVdFmgl8SDEG4Dce07brbNzdx3nUR7KgAVcoY8,12557
3
3
  hanzo_mcp/server.py,sha256=bV4ywWOgm7BwZrbZwv1qoRKbAsMYT08aCGQwuFS8raM,6678
4
4
  hanzo_mcp/tools/__init__.py,sha256=9LbWAPfSntDwLaAex3dagsHO4BgZQHKj5E6UX-Gmyb4,3496
5
5
  hanzo_mcp/tools/agent/__init__.py,sha256=0eyQqqdAy7WCZEqUfV6xh66bDpQI9neB6iDjWf0_pJI,2189
@@ -15,7 +15,7 @@ hanzo_mcp/tools/common/__init__.py,sha256=felrGAEqLWOa8fuHjTCS7khqtlA-izz8k865ky
15
15
  hanzo_mcp/tools/common/base.py,sha256=O7Lgft0XiC9Iyi3fYsmoWWrvKDK2Aa-FJLxPgnNJRJY,7341
16
16
  hanzo_mcp/tools/common/context.py,sha256=ReIfcm37j5qnLQ8G_-d88ad5uC1OKkjQZKG9HdJPybI,13145
17
17
  hanzo_mcp/tools/common/error_handling.py,sha256=rluaHpXV89pjcf8JxgYB6EdqVkcxihb3pyEO2gN-u7w,2789
18
- hanzo_mcp/tools/common/logging_config.py,sha256=b1swgWV3nuhpVT0TCcbxlOC0gmiRLmbey_t2LOWEMbU,2793
18
+ hanzo_mcp/tools/common/logging_config.py,sha256=664VEaV671t3_PG9qPMf_twVCQYendeQAqm-NuS32dU,3931
19
19
  hanzo_mcp/tools/common/permissions.py,sha256=4YCfA2PJUOl-z_47n5uaRXO8gAZ_shMaPhpi1dilgRE,7594
20
20
  hanzo_mcp/tools/common/session.py,sha256=csX5ZhgBjO2bdXXXPpsUPzOCc7Tib-apYe01AP8sh8k,2774
21
21
  hanzo_mcp/tools/common/think_tool.py,sha256=I-O6ipM-PUofkNoMMzv37Y_2Yfx9mh7F1upTTsfRN4M,4046
@@ -41,13 +41,13 @@ hanzo_mcp/tools/project/base.py,sha256=CniLAsjum5vC3cgvF9AqU-_ZY_0Nf9uaF2L_xV2ob
41
41
  hanzo_mcp/tools/project/project_analyze.py,sha256=6GLE_JcSiCy6kKdee0sMI5T2229A-Vpp98s2j_JD6yI,5711
42
42
  hanzo_mcp/tools/shell/__init__.py,sha256=lKgh0WXds4tZJ1tIL9MJbyMSzP6A9uZQALjGGBvyYc4,1679
43
43
  hanzo_mcp/tools/shell/base.py,sha256=OxKNWMp-fB-vozzWOE_hHvr5M_pFKSMIYfOX0dEOWzA,4836
44
- hanzo_mcp/tools/shell/command_executor.py,sha256=5GcJvg54uty9fl_tkGdWTBcHyjxuynQZ_Tv6qOyKgdk,32616
44
+ hanzo_mcp/tools/shell/command_executor.py,sha256=sNQEiU0qGVJQuq8HqMFD5h1N3CmOfSuoHj5UMpSnaBY,32707
45
45
  hanzo_mcp/tools/shell/run_command.py,sha256=r7HBw0lqabgkGnVsDXmLnrTo0SU9g8gLvzpa-9n-cmM,6891
46
46
  hanzo_mcp/tools/shell/run_script.py,sha256=CLYnDc0Ze8plkXU6d98RgE4UrBg-fwaMVdcn9Fc6Ixw,7432
47
47
  hanzo_mcp/tools/shell/script_tool.py,sha256=s63tawIZBvwgm_kU9P7A3D4v2ulVw7j4l_rpsa_zGuc,8680
48
- hanzo_mcp-0.3.1.dist-info/licenses/LICENSE,sha256=mf1qZGFsPGskoPgytp9B-RsahfKvXsBpmaAbTLGTt8Y,1063
49
- hanzo_mcp-0.3.1.dist-info/METADATA,sha256=ay2jJEkPi-ivKlvoCRyCNj57-M0tT36tL4w5nuK_SQ0,7550
50
- hanzo_mcp-0.3.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
51
- hanzo_mcp-0.3.1.dist-info/entry_points.txt,sha256=aRKOKXtuQr-idSr-yH4efnRl2v8te94AcgN3ysqqSYs,49
52
- hanzo_mcp-0.3.1.dist-info/top_level.txt,sha256=eGFANatA0MHWiVlpS56fTYRIShtibrSom1uXI6XU0GU,10
53
- hanzo_mcp-0.3.1.dist-info/RECORD,,
48
+ hanzo_mcp-0.3.3.dist-info/licenses/LICENSE,sha256=mf1qZGFsPGskoPgytp9B-RsahfKvXsBpmaAbTLGTt8Y,1063
49
+ hanzo_mcp-0.3.3.dist-info/METADATA,sha256=OyTlavBJpC_-79IRKfQo5aaHYsV2q9OMSsbO7kEcHS4,8029
50
+ hanzo_mcp-0.3.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
51
+ hanzo_mcp-0.3.3.dist-info/entry_points.txt,sha256=aRKOKXtuQr-idSr-yH4efnRl2v8te94AcgN3ysqqSYs,49
52
+ hanzo_mcp-0.3.3.dist-info/top_level.txt,sha256=eGFANatA0MHWiVlpS56fTYRIShtibrSom1uXI6XU0GU,10
53
+ hanzo_mcp-0.3.3.dist-info/RECORD,,