hanzo-mcp 0.3.4__tar.gz → 0.5.0__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.
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/PKG-INFO +35 -3
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/README.md +33 -2
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/__init__.py +1 -1
- hanzo_mcp-0.5.0/hanzo_mcp/cli.py +320 -0
- hanzo_mcp-0.5.0/hanzo_mcp/cli_enhanced.py +438 -0
- hanzo_mcp-0.5.0/hanzo_mcp/config/__init__.py +19 -0
- hanzo_mcp-0.5.0/hanzo_mcp/config/settings.py +388 -0
- hanzo_mcp-0.5.0/hanzo_mcp/config/tool_config.py +197 -0
- hanzo_mcp-0.5.0/hanzo_mcp/prompts/__init__.py +117 -0
- hanzo_mcp-0.5.0/hanzo_mcp/prompts/compact_conversation.py +77 -0
- hanzo_mcp-0.5.0/hanzo_mcp/prompts/create_release.py +38 -0
- hanzo_mcp-0.5.0/hanzo_mcp/prompts/project_system.py +120 -0
- hanzo_mcp-0.5.0/hanzo_mcp/prompts/project_todo_reminder.py +111 -0
- hanzo_mcp-0.5.0/hanzo_mcp/prompts/utils.py +286 -0
- hanzo_mcp-0.5.0/hanzo_mcp/server.py +204 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/__init__.py +162 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/agent/__init__.py +8 -11
- hanzo_mcp-0.5.0/hanzo_mcp/tools/agent/agent_tool.py +540 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/agent/prompt.py +16 -13
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/agent/tool_adapter.py +9 -9
- hanzo_mcp-0.5.0/hanzo_mcp/tools/common/__init__.py +31 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/common/base.py +79 -110
- hanzo_mcp-0.5.0/hanzo_mcp/tools/common/batch_tool.py +330 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/common/context.py +182 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/common/permissions.py +12 -12
- hanzo_mcp-0.5.0/hanzo_mcp/tools/common/thinking_tool.py +153 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/common/validation.py +62 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/filesystem/__init__.py +141 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/filesystem/base.py +32 -24
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/filesystem/content_replace.py +114 -107
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/filesystem/directory_tree.py +129 -105
- hanzo_mcp-0.5.0/hanzo_mcp/tools/filesystem/edit.py +279 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/filesystem/grep.py +458 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/filesystem/grep_ast_tool.py +250 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/filesystem/multi_edit.py +362 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/filesystem/read.py +255 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/filesystem/write.py +156 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/jupyter/__init__.py +88 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/jupyter/base.py +66 -57
- hanzo_mcp-0.3.4/hanzo_mcp/tools/jupyter/edit_notebook.py → hanzo_mcp-0.5.0/hanzo_mcp/tools/jupyter/notebook_edit.py +162 -139
- hanzo_mcp-0.5.0/hanzo_mcp/tools/jupyter/notebook_read.py +152 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/shell/__init__.py +29 -20
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/shell/base.py +87 -45
- hanzo_mcp-0.5.0/hanzo_mcp/tools/shell/bash_session.py +731 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/shell/bash_session_executor.py +295 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp/tools/shell/command_executor.py +435 -384
- hanzo_mcp-0.5.0/hanzo_mcp/tools/shell/run_command.py +357 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/shell/run_command_windows.py +328 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/shell/session_manager.py +196 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/shell/session_storage.py +325 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/todo/__init__.py +66 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/todo/base.py +319 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/todo/todo_read.py +148 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/todo/todo_write.py +378 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/vector/__init__.py +95 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/vector/infinity_store.py +365 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/vector/project_manager.py +361 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/vector/vector_index.py +115 -0
- hanzo_mcp-0.5.0/hanzo_mcp/tools/vector/vector_search.py +215 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp.egg-info/PKG-INFO +35 -3
- hanzo_mcp-0.5.0/hanzo_mcp.egg-info/SOURCES.txt +69 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp.egg-info/requires.txt +1 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/pyproject.toml +9 -21
- hanzo_mcp-0.5.0/tests/test_async_support.py +24 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/tests/test_cli.py +195 -8
- hanzo_mcp-0.3.4/hanzo_mcp/cli.py +0 -357
- hanzo_mcp-0.3.4/hanzo_mcp/server.py +0 -182
- hanzo_mcp-0.3.4/hanzo_mcp/tools/__init__.py +0 -86
- hanzo_mcp-0.3.4/hanzo_mcp/tools/agent/agent_tool.py +0 -474
- hanzo_mcp-0.3.4/hanzo_mcp/tools/agent/base_provider.py +0 -73
- hanzo_mcp-0.3.4/hanzo_mcp/tools/agent/litellm_provider.py +0 -45
- hanzo_mcp-0.3.4/hanzo_mcp/tools/agent/lmstudio_agent.py +0 -385
- hanzo_mcp-0.3.4/hanzo_mcp/tools/agent/lmstudio_provider.py +0 -219
- hanzo_mcp-0.3.4/hanzo_mcp/tools/agent/provider_registry.py +0 -120
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/__init__.py +0 -30
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/context.py +0 -448
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/error_handling.py +0 -86
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/logging_config.py +0 -115
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/session.py +0 -91
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/think_tool.py +0 -123
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/validation.py +0 -124
- hanzo_mcp-0.3.4/hanzo_mcp/tools/common/version_tool.py +0 -120
- hanzo_mcp-0.3.4/hanzo_mcp/tools/filesystem/__init__.py +0 -94
- hanzo_mcp-0.3.4/hanzo_mcp/tools/filesystem/edit_file.py +0 -287
- hanzo_mcp-0.3.4/hanzo_mcp/tools/filesystem/get_file_info.py +0 -170
- hanzo_mcp-0.3.4/hanzo_mcp/tools/filesystem/read_files.py +0 -198
- hanzo_mcp-0.3.4/hanzo_mcp/tools/filesystem/search_content.py +0 -275
- hanzo_mcp-0.3.4/hanzo_mcp/tools/filesystem/write_file.py +0 -162
- hanzo_mcp-0.3.4/hanzo_mcp/tools/jupyter/__init__.py +0 -76
- hanzo_mcp-0.3.4/hanzo_mcp/tools/jupyter/notebook_operations.py +0 -514
- hanzo_mcp-0.3.4/hanzo_mcp/tools/jupyter/read_notebook.py +0 -165
- hanzo_mcp-0.3.4/hanzo_mcp/tools/project/__init__.py +0 -64
- hanzo_mcp-0.3.4/hanzo_mcp/tools/project/analysis.py +0 -882
- hanzo_mcp-0.3.4/hanzo_mcp/tools/project/base.py +0 -66
- hanzo_mcp-0.3.4/hanzo_mcp/tools/project/project_analyze.py +0 -173
- hanzo_mcp-0.3.4/hanzo_mcp/tools/shell/run_command.py +0 -204
- hanzo_mcp-0.3.4/hanzo_mcp/tools/shell/run_script.py +0 -215
- hanzo_mcp-0.3.4/hanzo_mcp/tools/shell/script_tool.py +0 -244
- hanzo_mcp-0.3.4/hanzo_mcp.egg-info/SOURCES.txt +0 -61
- hanzo_mcp-0.3.4/tests/test_server.py +0 -191
- hanzo_mcp-0.3.4/tests/test_tools_registration.py +0 -180
- hanzo_mcp-0.3.4/tests/test_validation.py +0 -118
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/LICENSE +0 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp.egg-info/dependency_links.txt +0 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp.egg-info/entry_points.txt +0 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/hanzo_mcp.egg-info/top_level.txt +0 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/setup.cfg +0 -0
- {hanzo_mcp-0.3.4 → hanzo_mcp-0.5.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hanzo-mcp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: MCP implementation of Hanzo capabilities
|
|
5
5
|
Author-email: Hanzo Industries Inc <dev@hanzo.ai>
|
|
6
6
|
License: MIT
|
|
@@ -20,6 +20,7 @@ Requires-Dist: uvicorn>=0.23.1
|
|
|
20
20
|
Requires-Dist: openai>=1.50.0
|
|
21
21
|
Requires-Dist: python-dotenv>=1.0.0
|
|
22
22
|
Requires-Dist: litellm>=1.40.14
|
|
23
|
+
Requires-Dist: grep-ast>=0.8.1
|
|
23
24
|
Provides-Extra: dev
|
|
24
25
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
25
26
|
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
@@ -50,7 +51,7 @@ An implementation of Hanzo capabilities using the Model Context Protocol (MCP).
|
|
|
50
51
|
|
|
51
52
|
This project provides an MCP server that implements Hanzo-like functionality, allowing Claude to directly execute instructions for modifying and improving project files. By leveraging the Model Context Protocol, this implementation enables seamless integration with various MCP clients including Claude Desktop.
|
|
52
53
|
|
|
53
|
-

|
|
54
55
|
|
|
55
56
|
## Features
|
|
56
57
|
|
|
@@ -96,9 +97,40 @@ uv pip install hanzo-mcp
|
|
|
96
97
|
pip install hanzo-mcp
|
|
97
98
|
```
|
|
98
99
|
|
|
100
|
+
### Claude Desktop Integration
|
|
101
|
+
|
|
102
|
+
To install and configure hanzo-mcp for use with Claude Desktop:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Install the package globally
|
|
106
|
+
uv pip install hanzo-mcp
|
|
107
|
+
|
|
108
|
+
# Install configuration to Claude Desktop with default settings
|
|
109
|
+
hanzo-mcp --install
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For development, if you want to install your local version to Claude Desktop:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Clone and navigate to the repository
|
|
116
|
+
git clone https://github.com/hanzoai/mcp.git
|
|
117
|
+
cd mcp
|
|
118
|
+
|
|
119
|
+
# Install and configure for Claude Desktop
|
|
120
|
+
make install-desktop
|
|
121
|
+
|
|
122
|
+
# With custom paths and server name
|
|
123
|
+
make install-desktop ALLOWED_PATHS="/path/to/projects,/another/path" SERVER_NAME="hanzo-dev"
|
|
124
|
+
|
|
125
|
+
# Disable write tools (useful if you prefer using your IDE for edits)
|
|
126
|
+
make install-desktop DISABLE_WRITE=1
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
After installation, restart Claude Desktop. You'll see "hanzo" (or your custom server name) available in the MCP server dropdown.
|
|
130
|
+
|
|
99
131
|
For detailed installation and configuration instructions, please refer to the [documentation](./docs/).
|
|
100
132
|
|
|
101
|
-
Of course, you can also read [USEFUL_PROMPTS](./
|
|
133
|
+
Of course, you can also read [USEFUL_PROMPTS](./docs/USEFUL_PROMPTS.md) for some inspiration on how to use hanzo-mcp.
|
|
102
134
|
|
|
103
135
|
## Security
|
|
104
136
|
|
|
@@ -6,7 +6,7 @@ An implementation of Hanzo capabilities using the Model Context Protocol (MCP).
|
|
|
6
6
|
|
|
7
7
|
This project provides an MCP server that implements Hanzo-like functionality, allowing Claude to directly execute instructions for modifying and improving project files. By leveraging the Model Context Protocol, this implementation enables seamless integration with various MCP clients including Claude Desktop.
|
|
8
8
|
|
|
9
|
-

|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
@@ -52,9 +52,40 @@ uv pip install hanzo-mcp
|
|
|
52
52
|
pip install hanzo-mcp
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
### Claude Desktop Integration
|
|
56
|
+
|
|
57
|
+
To install and configure hanzo-mcp for use with Claude Desktop:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Install the package globally
|
|
61
|
+
uv pip install hanzo-mcp
|
|
62
|
+
|
|
63
|
+
# Install configuration to Claude Desktop with default settings
|
|
64
|
+
hanzo-mcp --install
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For development, if you want to install your local version to Claude Desktop:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Clone and navigate to the repository
|
|
71
|
+
git clone https://github.com/hanzoai/mcp.git
|
|
72
|
+
cd mcp
|
|
73
|
+
|
|
74
|
+
# Install and configure for Claude Desktop
|
|
75
|
+
make install-desktop
|
|
76
|
+
|
|
77
|
+
# With custom paths and server name
|
|
78
|
+
make install-desktop ALLOWED_PATHS="/path/to/projects,/another/path" SERVER_NAME="hanzo-dev"
|
|
79
|
+
|
|
80
|
+
# Disable write tools (useful if you prefer using your IDE for edits)
|
|
81
|
+
make install-desktop DISABLE_WRITE=1
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
After installation, restart Claude Desktop. You'll see "hanzo" (or your custom server name) available in the MCP server dropdown.
|
|
85
|
+
|
|
55
86
|
For detailed installation and configuration instructions, please refer to the [documentation](./docs/).
|
|
56
87
|
|
|
57
|
-
Of course, you can also read [USEFUL_PROMPTS](./
|
|
88
|
+
Of course, you can also read [USEFUL_PROMPTS](./docs/USEFUL_PROMPTS.md) for some inspiration on how to use hanzo-mcp.
|
|
58
89
|
|
|
59
90
|
## Security
|
|
60
91
|
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""Command-line interface for the Hanzo MCP server."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, cast
|
|
9
|
+
|
|
10
|
+
from hanzo_mcp.server import HanzoMCPServer
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main() -> None:
|
|
14
|
+
"""Run the CLI for the Hanzo MCP server."""
|
|
15
|
+
parser = argparse.ArgumentParser(
|
|
16
|
+
description="MCP server implementing Hanzo AI capabilities"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
_ = parser.add_argument(
|
|
20
|
+
"--transport",
|
|
21
|
+
choices=["stdio", "sse"],
|
|
22
|
+
default="stdio",
|
|
23
|
+
help="Transport protocol to use (default: stdio)",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
_ = parser.add_argument(
|
|
27
|
+
"--name",
|
|
28
|
+
default="hanzo-mcp",
|
|
29
|
+
help="Name of the MCP server (default: hanzo-mcp)",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
_ = parser.add_argument(
|
|
33
|
+
"--allow-path",
|
|
34
|
+
action="append",
|
|
35
|
+
dest="allowed_paths",
|
|
36
|
+
help="Add an allowed path (can be specified multiple times)",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
_ = parser.add_argument(
|
|
40
|
+
"--project",
|
|
41
|
+
action="append",
|
|
42
|
+
dest="project_paths",
|
|
43
|
+
help="Add a project path for prompt generation (can be specified multiple times)",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
_ = parser.add_argument(
|
|
47
|
+
"--agent-model",
|
|
48
|
+
dest="agent_model",
|
|
49
|
+
help="Specify the model name in LiteLLM format (e.g., 'openai/gpt-4o', 'anthropic/claude-4-sonnet')",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
_ = parser.add_argument(
|
|
53
|
+
"--agent-max-tokens",
|
|
54
|
+
dest="agent_max_tokens",
|
|
55
|
+
type=int,
|
|
56
|
+
help="Specify the maximum tokens for agent responses",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
_ = parser.add_argument(
|
|
60
|
+
"--agent-api-key",
|
|
61
|
+
dest="agent_api_key",
|
|
62
|
+
help="Specify the API key for the LLM provider (for development/testing only)",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
_ = parser.add_argument(
|
|
66
|
+
"--agent-base-url",
|
|
67
|
+
dest="agent_base_url",
|
|
68
|
+
help="Specify the base URL for the LLM provider API endpoint (e.g., 'http://localhost:1234/v1')",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
_ = parser.add_argument(
|
|
72
|
+
"--agent-max-iterations",
|
|
73
|
+
dest="agent_max_iterations",
|
|
74
|
+
type=int,
|
|
75
|
+
default=10,
|
|
76
|
+
help="Maximum number of iterations for agent (default: 10)",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
_ = parser.add_argument(
|
|
80
|
+
"--agent-max-tool-uses",
|
|
81
|
+
dest="agent_max_tool_uses",
|
|
82
|
+
type=int,
|
|
83
|
+
default=30,
|
|
84
|
+
help="Maximum number of total tool uses for agent (default: 30)",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
_ = parser.add_argument(
|
|
88
|
+
"--enable-agent-tool",
|
|
89
|
+
dest="enable_agent_tool",
|
|
90
|
+
action="store_true",
|
|
91
|
+
default=False,
|
|
92
|
+
help="Enable the agent tool (disabled by default)",
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
_ = parser.add_argument(
|
|
96
|
+
"--command-timeout",
|
|
97
|
+
dest="command_timeout",
|
|
98
|
+
type=float,
|
|
99
|
+
default=120.0,
|
|
100
|
+
help="Default timeout for command execution in seconds (default: 120.0)",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
_ = parser.add_argument(
|
|
104
|
+
"--disable-write-tools",
|
|
105
|
+
dest="disable_write_tools",
|
|
106
|
+
action="store_true",
|
|
107
|
+
default=False,
|
|
108
|
+
help="Disable write tools (edit, write, etc.)",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
_ = parser.add_argument(
|
|
112
|
+
"--disable-search-tools",
|
|
113
|
+
dest="disable_search_tools",
|
|
114
|
+
action="store_true",
|
|
115
|
+
default=False,
|
|
116
|
+
help="Disable search tools (grep, search_content, etc.)",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
_ = parser.add_argument(
|
|
120
|
+
"--host",
|
|
121
|
+
dest="host",
|
|
122
|
+
default="127.0.0.1",
|
|
123
|
+
help="Host for SSE server (default: 127.0.0.1)",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
_ = parser.add_argument(
|
|
127
|
+
"--port",
|
|
128
|
+
dest="port",
|
|
129
|
+
type=int,
|
|
130
|
+
default=3000,
|
|
131
|
+
help="Port for SSE server (default: 3000)",
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
_ = parser.add_argument(
|
|
135
|
+
"--log-level",
|
|
136
|
+
dest="log_level",
|
|
137
|
+
default="INFO",
|
|
138
|
+
choices=["DEBUG", "INFO", "WARNING", "ERROR"],
|
|
139
|
+
help="Logging level (default: INFO)",
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
_ = parser.add_argument(
|
|
143
|
+
"--project-dir",
|
|
144
|
+
dest="project_dir",
|
|
145
|
+
help="Single project directory (alias for --project)",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
_ = parser.add_argument(
|
|
149
|
+
"--install",
|
|
150
|
+
action="store_true",
|
|
151
|
+
help="Install server configuration in Claude Desktop",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
args = parser.parse_args()
|
|
155
|
+
|
|
156
|
+
# Cast args attributes to appropriate types to avoid 'Any' warnings
|
|
157
|
+
name: str = cast(str, args.name)
|
|
158
|
+
install: bool = cast(bool, args.install)
|
|
159
|
+
transport: str = cast(str, args.transport)
|
|
160
|
+
agent_model: str | None = cast(str | None, args.agent_model)
|
|
161
|
+
agent_max_tokens: int | None = cast(int | None, args.agent_max_tokens)
|
|
162
|
+
agent_api_key: str | None = cast(str | None, args.agent_api_key)
|
|
163
|
+
agent_base_url: str | None = cast(str | None, args.agent_base_url)
|
|
164
|
+
agent_max_iterations: int = cast(int, args.agent_max_iterations)
|
|
165
|
+
agent_max_tool_uses: int = cast(int, args.agent_max_tool_uses)
|
|
166
|
+
enable_agent_tool: bool = cast(bool, args.enable_agent_tool)
|
|
167
|
+
command_timeout: float = cast(float, args.command_timeout)
|
|
168
|
+
disable_write_tools: bool = cast(bool, args.disable_write_tools)
|
|
169
|
+
disable_search_tools: bool = cast(bool, args.disable_search_tools)
|
|
170
|
+
host: str = cast(str, args.host)
|
|
171
|
+
port: int = cast(int, args.port)
|
|
172
|
+
log_level: str = cast(str, args.log_level)
|
|
173
|
+
project_dir: str | None = cast(str | None, args.project_dir)
|
|
174
|
+
allowed_paths: list[str] = (
|
|
175
|
+
cast(list[str], args.allowed_paths) if args.allowed_paths else []
|
|
176
|
+
)
|
|
177
|
+
project_paths: list[str] = (
|
|
178
|
+
cast(list[str], args.project_paths) if args.project_paths else []
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Handle project_dir parameter (add to both allowed_paths and project_paths)
|
|
182
|
+
if project_dir:
|
|
183
|
+
if project_dir not in allowed_paths:
|
|
184
|
+
allowed_paths.append(project_dir)
|
|
185
|
+
if project_dir not in project_paths:
|
|
186
|
+
project_paths.append(project_dir)
|
|
187
|
+
|
|
188
|
+
if install:
|
|
189
|
+
install_claude_desktop_config(
|
|
190
|
+
name,
|
|
191
|
+
allowed_paths,
|
|
192
|
+
disable_write_tools,
|
|
193
|
+
disable_search_tools,
|
|
194
|
+
host,
|
|
195
|
+
port
|
|
196
|
+
)
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
# If no allowed paths are specified, use the current directory
|
|
200
|
+
if not allowed_paths:
|
|
201
|
+
allowed_paths = [os.getcwd()]
|
|
202
|
+
|
|
203
|
+
# Run the server
|
|
204
|
+
server = HanzoMCPServer(
|
|
205
|
+
name=name,
|
|
206
|
+
allowed_paths=allowed_paths,
|
|
207
|
+
project_dir=project_dir,
|
|
208
|
+
agent_model=agent_model,
|
|
209
|
+
agent_max_tokens=agent_max_tokens,
|
|
210
|
+
agent_api_key=agent_api_key,
|
|
211
|
+
agent_base_url=agent_base_url,
|
|
212
|
+
agent_max_iterations=agent_max_iterations,
|
|
213
|
+
agent_max_tool_uses=agent_max_tool_uses,
|
|
214
|
+
enable_agent_tool=enable_agent_tool,
|
|
215
|
+
disable_write_tools=disable_write_tools,
|
|
216
|
+
disable_search_tools=disable_search_tools,
|
|
217
|
+
host=host,
|
|
218
|
+
port=port,
|
|
219
|
+
)
|
|
220
|
+
# Transport will be automatically cast to Literal['stdio', 'sse'] by the server
|
|
221
|
+
server.run(transport=transport)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def install_claude_desktop_config(
|
|
225
|
+
name: str = "hanzo-mcp",
|
|
226
|
+
allowed_paths: list[str] | None = None,
|
|
227
|
+
disable_write_tools: bool = False,
|
|
228
|
+
disable_search_tools: bool = False,
|
|
229
|
+
host: str = "127.0.0.1",
|
|
230
|
+
port: int = 3000,
|
|
231
|
+
) -> None:
|
|
232
|
+
"""Install the server configuration in Claude Desktop.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
name: The name to use for the server in the config
|
|
236
|
+
allowed_paths: Optional list of paths to allow
|
|
237
|
+
disable_write_tools: Whether to disable write tools
|
|
238
|
+
disable_search_tools: Whether to disable search tools
|
|
239
|
+
host: Host for SSE server
|
|
240
|
+
port: Port for SSE server
|
|
241
|
+
"""
|
|
242
|
+
# Find the Claude Desktop config directory
|
|
243
|
+
home: Path = Path.home()
|
|
244
|
+
|
|
245
|
+
if sys.platform == "darwin": # macOS
|
|
246
|
+
config_dir: Path = home / "Library" / "Application Support" / "Claude"
|
|
247
|
+
elif sys.platform == "win32": # Windows
|
|
248
|
+
config_dir = Path(os.environ.get("APPDATA", "")) / "Claude"
|
|
249
|
+
else: # Linux and others
|
|
250
|
+
config_dir = home / ".config" / "claude"
|
|
251
|
+
|
|
252
|
+
config_file: Path = config_dir / "claude_desktop_config.json"
|
|
253
|
+
|
|
254
|
+
# Create directory if it doesn't exist
|
|
255
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
256
|
+
|
|
257
|
+
# Get current script path
|
|
258
|
+
script_path: Path = Path(sys.executable)
|
|
259
|
+
|
|
260
|
+
# Create args array
|
|
261
|
+
args: list[str] = ["-m", "hanzo_mcp.cli"]
|
|
262
|
+
|
|
263
|
+
# Add allowed paths if specified
|
|
264
|
+
if allowed_paths:
|
|
265
|
+
for path in allowed_paths:
|
|
266
|
+
args.extend(["--allow-path", path])
|
|
267
|
+
else:
|
|
268
|
+
# Allow home directory by default
|
|
269
|
+
args.extend(["--allow-path", str(home)])
|
|
270
|
+
|
|
271
|
+
# Add tool disable flags if specified
|
|
272
|
+
if disable_write_tools:
|
|
273
|
+
args.append("--disable-write-tools")
|
|
274
|
+
|
|
275
|
+
if disable_search_tools:
|
|
276
|
+
args.append("--disable-search-tools")
|
|
277
|
+
|
|
278
|
+
# Create config object
|
|
279
|
+
config: dict[str, Any] = {
|
|
280
|
+
"mcpServers": {name: {"command": script_path.as_posix(), "args": args}}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
# Check if the file already exists
|
|
284
|
+
if config_file.exists():
|
|
285
|
+
try:
|
|
286
|
+
with open(config_file, "r") as f:
|
|
287
|
+
existing_config: dict[str, Any] = json.load(f)
|
|
288
|
+
|
|
289
|
+
# Update the existing config
|
|
290
|
+
if "mcpServers" not in existing_config:
|
|
291
|
+
existing_config["mcpServers"] = {}
|
|
292
|
+
|
|
293
|
+
existing_config["mcpServers"][name] = config["mcpServers"][name]
|
|
294
|
+
config = existing_config
|
|
295
|
+
except Exception as e:
|
|
296
|
+
print(f"Error reading existing config: {e}")
|
|
297
|
+
print("Creating new config file.")
|
|
298
|
+
|
|
299
|
+
# Write the config file
|
|
300
|
+
with open(config_file, mode="w") as f:
|
|
301
|
+
json.dump(config, f, indent=2)
|
|
302
|
+
|
|
303
|
+
print(f"Successfully installed {name} in Claude Desktop configuration.")
|
|
304
|
+
print(f"Config file: {config_file}")
|
|
305
|
+
|
|
306
|
+
if allowed_paths:
|
|
307
|
+
print("\nAllowed paths:")
|
|
308
|
+
for path in allowed_paths:
|
|
309
|
+
print(f"- {path}")
|
|
310
|
+
else:
|
|
311
|
+
print(f"\nDefault allowed path: {home}")
|
|
312
|
+
|
|
313
|
+
print(
|
|
314
|
+
"\nYou can modify allowed paths in the config file directly."
|
|
315
|
+
)
|
|
316
|
+
print("Restart Claude Desktop for changes to take effect.")
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
if __name__ == "__main__":
|
|
320
|
+
main()
|