hanzo-mcp 0.8.8__py3-none-any.whl → 0.8.13__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 +1 -3
- hanzo_mcp/analytics/posthog_analytics.py +4 -17
- hanzo_mcp/bridge.py +9 -25
- hanzo_mcp/cli.py +8 -17
- hanzo_mcp/cli_enhanced.py +5 -14
- hanzo_mcp/cli_plugin.py +3 -9
- hanzo_mcp/config/settings.py +6 -20
- hanzo_mcp/config/tool_config.py +2 -4
- hanzo_mcp/core/base_agent.py +88 -88
- hanzo_mcp/core/model_registry.py +238 -210
- hanzo_mcp/dev_server.py +5 -15
- hanzo_mcp/prompts/__init__.py +2 -6
- hanzo_mcp/prompts/project_todo_reminder.py +3 -9
- hanzo_mcp/prompts/tool_explorer.py +1 -3
- hanzo_mcp/prompts/utils.py +7 -21
- hanzo_mcp/server.py +6 -7
- hanzo_mcp/tools/__init__.py +13 -29
- hanzo_mcp/tools/agent/__init__.py +2 -1
- hanzo_mcp/tools/agent/agent.py +10 -30
- hanzo_mcp/tools/agent/agent_tool.py +6 -17
- hanzo_mcp/tools/agent/agent_tool_v1_deprecated.py +15 -42
- hanzo_mcp/tools/agent/claude_desktop_auth.py +3 -9
- hanzo_mcp/tools/agent/cli_agent_base.py +7 -24
- hanzo_mcp/tools/agent/cli_tools.py +76 -75
- hanzo_mcp/tools/agent/code_auth.py +1 -3
- hanzo_mcp/tools/agent/code_auth_tool.py +2 -6
- hanzo_mcp/tools/agent/critic_tool.py +8 -24
- hanzo_mcp/tools/agent/iching_tool.py +12 -36
- hanzo_mcp/tools/agent/network_tool.py +7 -18
- hanzo_mcp/tools/agent/prompt.py +1 -5
- hanzo_mcp/tools/agent/review_tool.py +10 -25
- hanzo_mcp/tools/agent/swarm_alias.py +1 -3
- hanzo_mcp/tools/agent/swarm_tool.py +16 -41
- hanzo_mcp/tools/agent/swarm_tool_v1_deprecated.py +11 -39
- hanzo_mcp/tools/agent/unified_cli_tools.py +38 -38
- hanzo_mcp/tools/common/batch_tool.py +15 -45
- hanzo_mcp/tools/common/config_tool.py +9 -28
- hanzo_mcp/tools/common/context.py +1 -3
- hanzo_mcp/tools/common/critic_tool.py +1 -3
- hanzo_mcp/tools/common/decorators.py +2 -6
- hanzo_mcp/tools/common/enhanced_base.py +2 -6
- hanzo_mcp/tools/common/fastmcp_pagination.py +4 -12
- hanzo_mcp/tools/common/forgiving_edit.py +9 -28
- hanzo_mcp/tools/common/mode.py +1 -5
- hanzo_mcp/tools/common/paginated_base.py +3 -11
- hanzo_mcp/tools/common/paginated_response.py +10 -30
- hanzo_mcp/tools/common/pagination.py +3 -9
- hanzo_mcp/tools/common/permissions.py +3 -9
- hanzo_mcp/tools/common/personality.py +9 -34
- hanzo_mcp/tools/common/plugin_loader.py +3 -15
- hanzo_mcp/tools/common/stats.py +7 -19
- hanzo_mcp/tools/common/thinking_tool.py +1 -3
- hanzo_mcp/tools/common/tool_disable.py +2 -6
- hanzo_mcp/tools/common/tool_list.py +2 -6
- hanzo_mcp/tools/common/validation.py +1 -3
- hanzo_mcp/tools/config/config_tool.py +7 -13
- hanzo_mcp/tools/config/index_config.py +1 -3
- hanzo_mcp/tools/config/mode_tool.py +5 -15
- hanzo_mcp/tools/database/database_manager.py +3 -9
- hanzo_mcp/tools/database/graph.py +1 -3
- hanzo_mcp/tools/database/graph_add.py +3 -9
- hanzo_mcp/tools/database/graph_query.py +11 -34
- hanzo_mcp/tools/database/graph_remove.py +3 -9
- hanzo_mcp/tools/database/graph_search.py +6 -20
- hanzo_mcp/tools/database/graph_stats.py +11 -33
- hanzo_mcp/tools/database/sql.py +4 -12
- hanzo_mcp/tools/database/sql_query.py +6 -10
- hanzo_mcp/tools/database/sql_search.py +2 -6
- hanzo_mcp/tools/database/sql_stats.py +5 -15
- hanzo_mcp/tools/editor/neovim_command.py +1 -3
- hanzo_mcp/tools/editor/neovim_session.py +7 -13
- hanzo_mcp/tools/filesystem/__init__.py +2 -3
- hanzo_mcp/tools/filesystem/ast_multi_edit.py +14 -43
- hanzo_mcp/tools/filesystem/base.py +4 -12
- hanzo_mcp/tools/filesystem/batch_search.py +35 -115
- hanzo_mcp/tools/filesystem/content_replace.py +4 -12
- hanzo_mcp/tools/filesystem/diff.py +2 -10
- hanzo_mcp/tools/filesystem/directory_tree.py +9 -27
- hanzo_mcp/tools/filesystem/directory_tree_paginated.py +5 -15
- hanzo_mcp/tools/filesystem/edit.py +6 -18
- hanzo_mcp/tools/filesystem/find.py +3 -9
- hanzo_mcp/tools/filesystem/find_files.py +2 -6
- hanzo_mcp/tools/filesystem/git_search.py +9 -24
- hanzo_mcp/tools/filesystem/grep.py +9 -27
- hanzo_mcp/tools/filesystem/multi_edit.py +6 -18
- hanzo_mcp/tools/filesystem/read.py +8 -26
- hanzo_mcp/tools/filesystem/rules_tool.py +6 -17
- hanzo_mcp/tools/filesystem/search_tool.py +18 -62
- hanzo_mcp/tools/filesystem/symbols_tool.py +5 -15
- hanzo_mcp/tools/filesystem/tree.py +1 -3
- hanzo_mcp/tools/filesystem/watch.py +1 -3
- hanzo_mcp/tools/filesystem/write.py +1 -3
- hanzo_mcp/tools/jupyter/base.py +6 -20
- hanzo_mcp/tools/jupyter/jupyter.py +4 -12
- hanzo_mcp/tools/jupyter/notebook_edit.py +11 -35
- hanzo_mcp/tools/jupyter/notebook_read.py +2 -6
- hanzo_mcp/tools/llm/consensus_tool.py +8 -24
- hanzo_mcp/tools/llm/llm_manage.py +2 -6
- hanzo_mcp/tools/llm/llm_tool.py +17 -58
- hanzo_mcp/tools/llm/llm_unified.py +18 -59
- hanzo_mcp/tools/llm/provider_tools.py +1 -3
- hanzo_mcp/tools/lsp/lsp_tool.py +5 -17
- hanzo_mcp/tools/mcp/mcp_add.py +3 -5
- hanzo_mcp/tools/mcp/mcp_remove.py +1 -1
- hanzo_mcp/tools/mcp/mcp_stats.py +1 -3
- hanzo_mcp/tools/mcp/mcp_tool.py +9 -23
- hanzo_mcp/tools/memory/__init__.py +33 -40
- hanzo_mcp/tools/memory/knowledge_tools.py +7 -25
- hanzo_mcp/tools/memory/memory_tools.py +7 -19
- hanzo_mcp/tools/search/find_tool.py +10 -32
- hanzo_mcp/tools/search/unified_search.py +27 -81
- hanzo_mcp/tools/shell/__init__.py +2 -2
- hanzo_mcp/tools/shell/auto_background.py +2 -6
- hanzo_mcp/tools/shell/base.py +1 -5
- hanzo_mcp/tools/shell/base_process.py +5 -7
- hanzo_mcp/tools/shell/bash_session.py +7 -24
- hanzo_mcp/tools/shell/bash_session_executor.py +5 -15
- hanzo_mcp/tools/shell/bash_tool.py +3 -7
- hanzo_mcp/tools/shell/command_executor.py +26 -79
- hanzo_mcp/tools/shell/logs.py +4 -16
- hanzo_mcp/tools/shell/npx.py +2 -8
- hanzo_mcp/tools/shell/npx_tool.py +1 -3
- hanzo_mcp/tools/shell/pkill.py +4 -12
- hanzo_mcp/tools/shell/process_tool.py +2 -8
- hanzo_mcp/tools/shell/processes.py +5 -17
- hanzo_mcp/tools/shell/run_background.py +1 -3
- hanzo_mcp/tools/shell/run_command.py +1 -3
- hanzo_mcp/tools/shell/run_command_windows.py +1 -3
- hanzo_mcp/tools/shell/session_manager.py +2 -6
- hanzo_mcp/tools/shell/session_storage.py +2 -6
- hanzo_mcp/tools/shell/streaming_command.py +7 -23
- hanzo_mcp/tools/shell/uvx.py +4 -14
- hanzo_mcp/tools/shell/uvx_background.py +2 -6
- hanzo_mcp/tools/shell/uvx_tool.py +1 -3
- hanzo_mcp/tools/shell/zsh_tool.py +12 -20
- hanzo_mcp/tools/todo/todo.py +1 -3
- hanzo_mcp/tools/todo/todo_read.py +3 -9
- hanzo_mcp/tools/todo/todo_write.py +6 -18
- hanzo_mcp/tools/vector/__init__.py +3 -9
- hanzo_mcp/tools/vector/ast_analyzer.py +6 -20
- hanzo_mcp/tools/vector/git_ingester.py +10 -30
- hanzo_mcp/tools/vector/index_tool.py +3 -9
- hanzo_mcp/tools/vector/infinity_store.py +11 -30
- hanzo_mcp/tools/vector/mock_infinity.py +159 -0
- hanzo_mcp/tools/vector/project_manager.py +4 -12
- hanzo_mcp/tools/vector/vector.py +2 -6
- hanzo_mcp/tools/vector/vector_index.py +8 -8
- hanzo_mcp/tools/vector/vector_search.py +7 -21
- {hanzo_mcp-0.8.8.dist-info → hanzo_mcp-0.8.13.dist-info}/METADATA +2 -2
- hanzo_mcp-0.8.13.dist-info/RECORD +193 -0
- hanzo_mcp-0.8.8.dist-info/RECORD +0 -192
- {hanzo_mcp-0.8.8.dist-info → hanzo_mcp-0.8.13.dist-info}/WHEEL +0 -0
- {hanzo_mcp-0.8.8.dist-info → hanzo_mcp-0.8.13.dist-info}/entry_points.txt +0 -0
- {hanzo_mcp-0.8.8.dist-info → hanzo_mcp-0.8.13.dist-info}/top_level.txt +0 -0
|
@@ -71,9 +71,7 @@ class ProviderToolParams(TypedDict, total=False):
|
|
|
71
71
|
class BaseProviderTool(BaseTool):
|
|
72
72
|
"""Base class for provider-specific LLM tools."""
|
|
73
73
|
|
|
74
|
-
def __init__(
|
|
75
|
-
self, provider: str, default_model: str, model_variants: Dict[str, str]
|
|
76
|
-
):
|
|
74
|
+
def __init__(self, provider: str, default_model: str, model_variants: Dict[str, str]):
|
|
77
75
|
"""Initialize provider tool.
|
|
78
76
|
|
|
79
77
|
Args:
|
hanzo_mcp/tools/lsp/lsp_tool.py
CHANGED
|
@@ -297,9 +297,7 @@ class LSPTool(BaseTool):
|
|
|
297
297
|
self.logger.error(f"Installation error: {e}")
|
|
298
298
|
return False
|
|
299
299
|
|
|
300
|
-
async def _ensure_lsp_running(
|
|
301
|
-
self, language: str, root_uri: str
|
|
302
|
-
) -> Optional[LSPServer]:
|
|
300
|
+
async def _ensure_lsp_running(self, language: str, root_uri: str) -> Optional[LSPServer]:
|
|
303
301
|
"""Ensure LSP server is running for language."""
|
|
304
302
|
# Check if already running
|
|
305
303
|
server_key = f"{language}:{root_uri}"
|
|
@@ -326,9 +324,7 @@ class LSPTool(BaseTool):
|
|
|
326
324
|
cwd=root_uri,
|
|
327
325
|
)
|
|
328
326
|
|
|
329
|
-
server = LSPServer(
|
|
330
|
-
language=language, process=process, config=config, root_uri=root_uri
|
|
331
|
-
)
|
|
327
|
+
server = LSPServer(language=language, process=process, config=config, root_uri=root_uri)
|
|
332
328
|
|
|
333
329
|
# Initialize LSP
|
|
334
330
|
await self._initialize_lsp(server)
|
|
@@ -367,9 +363,7 @@ class LSPTool(BaseTool):
|
|
|
367
363
|
await self._send_request(server, request)
|
|
368
364
|
server.initialized = True
|
|
369
365
|
|
|
370
|
-
async def _send_request(
|
|
371
|
-
self, server: LSPServer, request: Dict[str, Any]
|
|
372
|
-
) -> Optional[Dict[str, Any]]:
|
|
366
|
+
async def _send_request(self, server: LSPServer, request: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
373
367
|
"""Send JSON-RPC request to LSP server."""
|
|
374
368
|
if not server.process or server.process.returncode is not None:
|
|
375
369
|
return None
|
|
@@ -426,11 +420,7 @@ class LSPTool(BaseTool):
|
|
|
426
420
|
"status",
|
|
427
421
|
]
|
|
428
422
|
if action not in valid_actions:
|
|
429
|
-
return MCPResourceDocument(
|
|
430
|
-
data={
|
|
431
|
-
"error": f"Invalid action. Must be one of: {', '.join(valid_actions)}"
|
|
432
|
-
}
|
|
433
|
-
)
|
|
423
|
+
return MCPResourceDocument(data={"error": f"Invalid action. Must be one of: {', '.join(valid_actions)}"})
|
|
434
424
|
|
|
435
425
|
# Get language from file
|
|
436
426
|
language = self._get_language_from_file(file)
|
|
@@ -478,9 +468,7 @@ class LSPTool(BaseTool):
|
|
|
478
468
|
)
|
|
479
469
|
|
|
480
470
|
# Execute action
|
|
481
|
-
result = await self._execute_lsp_action(
|
|
482
|
-
server, action, file, line, character, new_name
|
|
483
|
-
)
|
|
471
|
+
result = await self._execute_lsp_action(server, action, file, line, character, new_name)
|
|
484
472
|
|
|
485
473
|
return MCPResourceDocument(data=result)
|
|
486
474
|
|
hanzo_mcp/tools/mcp/mcp_add.py
CHANGED
|
@@ -189,9 +189,7 @@ Use 'mcp_stats' to see all added servers and their status.
|
|
|
189
189
|
|
|
190
190
|
full_command = shlex.split(command)
|
|
191
191
|
|
|
192
|
-
await tool_ctx.info(
|
|
193
|
-
f"Adding MCP server '{name}' with command: {' '.join(full_command)}"
|
|
194
|
-
)
|
|
192
|
+
await tool_ctx.info(f"Adding MCP server '{name}' with command: {' '.join(full_command)}")
|
|
195
193
|
|
|
196
194
|
# Create server configuration
|
|
197
195
|
server_config = {
|
|
@@ -221,8 +219,8 @@ Use 'mcp_stats' to see all added servers and their status.
|
|
|
221
219
|
if not shutil.which("uvx"):
|
|
222
220
|
return "Error: uvx not found. Install uv first."
|
|
223
221
|
|
|
224
|
-
#
|
|
225
|
-
#
|
|
222
|
+
# TODO: Actually start and connect to the MCP server
|
|
223
|
+
# For now, we just store the configuration
|
|
226
224
|
server_config["status"] = "ready"
|
|
227
225
|
|
|
228
226
|
except Exception as e:
|
|
@@ -103,7 +103,7 @@ Use 'mcp_stats' to see all servers before removing.
|
|
|
103
103
|
if not force:
|
|
104
104
|
return f"Error: Server '{name}' is currently running. Use --force to remove anyway."
|
|
105
105
|
else:
|
|
106
|
-
#
|
|
106
|
+
# TODO: Stop the server process
|
|
107
107
|
await tool_ctx.info(f"Stopping running server '{name}'")
|
|
108
108
|
|
|
109
109
|
# Remove from registry
|
hanzo_mcp/tools/mcp/mcp_stats.py
CHANGED
|
@@ -68,9 +68,7 @@ Example:
|
|
|
68
68
|
servers = McpAddTool.get_servers()
|
|
69
69
|
|
|
70
70
|
if not servers:
|
|
71
|
-
return
|
|
72
|
-
"No MCP servers have been added yet.\n\nUse 'mcp_add' to add servers."
|
|
73
|
-
)
|
|
71
|
+
return "No MCP servers have been added yet.\n\nUse 'mcp_add' to add servers."
|
|
74
72
|
|
|
75
73
|
output = []
|
|
76
74
|
output.append("=== MCP Server Statistics ===")
|
hanzo_mcp/tools/mcp/mcp_tool.py
CHANGED
|
@@ -173,9 +173,7 @@ class MCPTool(BaseTool):
|
|
|
173
173
|
def _auto_start_servers(self):
|
|
174
174
|
"""Auto-start servers configured for auto-start."""
|
|
175
175
|
for name, server_config in self.config.get("servers", {}).items():
|
|
176
|
-
if server_config.get("enabled", False) and server_config.get(
|
|
177
|
-
"auto_start", False
|
|
178
|
-
):
|
|
176
|
+
if server_config.get("enabled", False) and server_config.get("auto_start", False):
|
|
179
177
|
self._start_server(name, server_config)
|
|
180
178
|
|
|
181
179
|
def _start_server(self, name: str, config: Dict[str, Any]) -> bool:
|
|
@@ -202,9 +200,7 @@ class MCPTool(BaseTool):
|
|
|
202
200
|
cmd = [config["command"]] + config.get("args", [])
|
|
203
201
|
|
|
204
202
|
# Create log directory
|
|
205
|
-
log_dir = Path(
|
|
206
|
-
self.config.get("log_dir", str(Path.home() / ".hanzo" / "mcp" / "logs"))
|
|
207
|
-
)
|
|
203
|
+
log_dir = Path(self.config.get("log_dir", str(Path.home() / ".hanzo" / "mcp" / "logs")))
|
|
208
204
|
log_dir.mkdir(parents=True, exist_ok=True)
|
|
209
205
|
|
|
210
206
|
# Start process
|
|
@@ -307,11 +303,11 @@ Status: {enabled} enabled, {running} running"""
|
|
|
307
303
|
elif action == "restart":
|
|
308
304
|
return self._handle_restart(params.get("name"))
|
|
309
305
|
elif action == "config":
|
|
310
|
-
return self._handle_config(
|
|
311
|
-
params.get("config_key"), params.get("config_value")
|
|
312
|
-
)
|
|
306
|
+
return self._handle_config(params.get("config_key"), params.get("config_value"))
|
|
313
307
|
else:
|
|
314
|
-
return
|
|
308
|
+
return (
|
|
309
|
+
f"Error: Unknown action '{action}'. Valid actions: list, add, remove, enable, disable, restart, config"
|
|
310
|
+
)
|
|
315
311
|
|
|
316
312
|
def _handle_list(self) -> str:
|
|
317
313
|
"""List all MCP servers."""
|
|
@@ -355,9 +351,7 @@ Status: {enabled} enabled, {running} running"""
|
|
|
355
351
|
output.append(f"{name}: {status}")
|
|
356
352
|
if config.get("description"):
|
|
357
353
|
output.append(f" Description: {config['description']}")
|
|
358
|
-
output.append(
|
|
359
|
-
f" Command: {config['command']} {' '.join(config.get('args', []))}"
|
|
360
|
-
)
|
|
354
|
+
output.append(f" Command: {config['command']} {' '.join(config.get('args', []))}")
|
|
361
355
|
|
|
362
356
|
if config.get("env"):
|
|
363
357
|
env_str = ", ".join([f"{k}={v}" for k, v in config["env"].items()])
|
|
@@ -498,11 +492,7 @@ Status: {enabled} enabled, {running} running"""
|
|
|
498
492
|
else:
|
|
499
493
|
return f"Configuration key '{key}' not found"
|
|
500
494
|
|
|
501
|
-
return (
|
|
502
|
-
json.dumps(current, indent=2)
|
|
503
|
-
if isinstance(current, (dict, list))
|
|
504
|
-
else str(current)
|
|
505
|
-
)
|
|
495
|
+
return json.dumps(current, indent=2) if isinstance(current, (dict, list)) else str(current)
|
|
506
496
|
else:
|
|
507
497
|
# Set value
|
|
508
498
|
# Navigate to parent
|
|
@@ -513,11 +503,7 @@ Status: {enabled} enabled, {running} running"""
|
|
|
513
503
|
current = current[k]
|
|
514
504
|
|
|
515
505
|
# Parse value if it looks like JSON
|
|
516
|
-
if (
|
|
517
|
-
isinstance(value, str)
|
|
518
|
-
and value.startswith("{")
|
|
519
|
-
or value.startswith("[")
|
|
520
|
-
):
|
|
506
|
+
if isinstance(value, str) and value.startswith("{") or value.startswith("["):
|
|
521
507
|
try:
|
|
522
508
|
value = json.loads(value)
|
|
523
509
|
except Exception:
|
|
@@ -4,19 +4,26 @@ from mcp.server import FastMCP
|
|
|
4
4
|
|
|
5
5
|
from hanzo_mcp.tools.common.base import BaseTool, ToolRegistry
|
|
6
6
|
from hanzo_mcp.tools.common.permissions import PermissionManager
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
|
|
8
|
+
# Import memory tools if available
|
|
9
|
+
try:
|
|
10
|
+
from hanzo_mcp.tools.memory.memory_tools import (
|
|
11
|
+
CreateMemoriesTool,
|
|
12
|
+
DeleteMemoriesTool,
|
|
13
|
+
ManageMemoriesTool,
|
|
14
|
+
RecallMemoriesTool,
|
|
15
|
+
UpdateMemoriesTool,
|
|
16
|
+
)
|
|
17
|
+
from hanzo_mcp.tools.memory.knowledge_tools import (
|
|
18
|
+
StoreFactsTool,
|
|
19
|
+
RecallFactsTool,
|
|
20
|
+
SummarizeToMemoryTool,
|
|
21
|
+
ManageKnowledgeBasesTool,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
MEMORY_TOOLS_AVAILABLE = True
|
|
25
|
+
except ImportError:
|
|
26
|
+
MEMORY_TOOLS_AVAILABLE = False
|
|
20
27
|
|
|
21
28
|
|
|
22
29
|
def register_memory_tools(
|
|
@@ -38,36 +45,22 @@ def register_memory_tools(
|
|
|
38
45
|
Returns:
|
|
39
46
|
List of registered tools
|
|
40
47
|
"""
|
|
48
|
+
if not MEMORY_TOOLS_AVAILABLE:
|
|
49
|
+
print("Warning: Memory tools not available (hanzo-memory package not found)")
|
|
50
|
+
return []
|
|
51
|
+
|
|
41
52
|
# Create memory tools
|
|
42
|
-
recall_tool = RecallMemoriesTool(
|
|
43
|
-
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
update_tool = UpdateMemoriesTool(
|
|
49
|
-
user_id=user_id, project_id=project_id, **memory_config
|
|
50
|
-
)
|
|
51
|
-
delete_tool = DeleteMemoriesTool(
|
|
52
|
-
user_id=user_id, project_id=project_id, **memory_config
|
|
53
|
-
)
|
|
54
|
-
manage_tool = ManageMemoriesTool(
|
|
55
|
-
user_id=user_id, project_id=project_id, **memory_config
|
|
56
|
-
)
|
|
53
|
+
recall_tool = RecallMemoriesTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
54
|
+
create_tool = CreateMemoriesTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
55
|
+
update_tool = UpdateMemoriesTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
56
|
+
delete_tool = DeleteMemoriesTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
57
|
+
manage_tool = ManageMemoriesTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
57
58
|
|
|
58
59
|
# Create knowledge tools
|
|
59
|
-
recall_facts_tool = RecallFactsTool(
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
user_id=user_id, project_id=project_id, **memory_config
|
|
64
|
-
)
|
|
65
|
-
summarize_tool = SummarizeToMemoryTool(
|
|
66
|
-
user_id=user_id, project_id=project_id, **memory_config
|
|
67
|
-
)
|
|
68
|
-
manage_kb_tool = ManageKnowledgeBasesTool(
|
|
69
|
-
user_id=user_id, project_id=project_id, **memory_config
|
|
70
|
-
)
|
|
60
|
+
recall_facts_tool = RecallFactsTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
61
|
+
store_facts_tool = StoreFactsTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
62
|
+
summarize_tool = SummarizeToMemoryTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
63
|
+
manage_kb_tool = ManageKnowledgeBasesTool(user_id=user_id, project_id=project_id, **memory_config)
|
|
71
64
|
|
|
72
65
|
# Register tools
|
|
73
66
|
ToolRegistry.register_tool(mcp_server, recall_tool)
|
|
@@ -140,15 +140,9 @@ recall_facts(queries=["company policies"], scope="global", limit=5)
|
|
|
140
140
|
if fact.metadata and fact.metadata.get("kb_name"):
|
|
141
141
|
kb_info = f" (KB: {fact.metadata['kb_name']})"
|
|
142
142
|
formatted.append(f"{i}. {fact.content}{kb_info}")
|
|
143
|
-
if (
|
|
144
|
-
fact.metadata and len(fact.metadata) > 2
|
|
145
|
-
): # More than just type and kb_name
|
|
143
|
+
if fact.metadata and len(fact.metadata) > 2: # More than just type and kb_name
|
|
146
144
|
# Show other metadata
|
|
147
|
-
other_meta = {
|
|
148
|
-
k: v
|
|
149
|
-
for k, v in fact.metadata.items()
|
|
150
|
-
if k not in ["type", "kb_name"]
|
|
151
|
-
}
|
|
145
|
+
other_meta = {k: v for k, v in fact.metadata.items() if k not in ["type", "kb_name"]}
|
|
152
146
|
if other_meta:
|
|
153
147
|
formatted.append(f" Metadata: {other_meta}")
|
|
154
148
|
|
|
@@ -167,9 +161,7 @@ recall_facts(queries=["company policies"], scope="global", limit=5)
|
|
|
167
161
|
scope: str = "project",
|
|
168
162
|
limit: int = 10,
|
|
169
163
|
) -> str:
|
|
170
|
-
return await tool_self.call(
|
|
171
|
-
ctx, queries=queries, kb_name=kb_name, scope=scope, limit=limit
|
|
172
|
-
)
|
|
164
|
+
return await tool_self.call(ctx, queries=queries, kb_name=kb_name, scope=scope, limit=limit)
|
|
173
165
|
|
|
174
166
|
|
|
175
167
|
@final
|
|
@@ -265,9 +257,7 @@ store_facts(facts=["Company founded in 2020"], scope="global", kb_name="company_
|
|
|
265
257
|
scope: str = "project",
|
|
266
258
|
metadata: Optional[Dict[str, Any]] = None,
|
|
267
259
|
) -> str:
|
|
268
|
-
return await tool_self.call(
|
|
269
|
-
ctx, facts=facts, kb_name=kb_name, scope=scope, metadata=metadata
|
|
270
|
-
)
|
|
260
|
+
return await tool_self.call(ctx, facts=facts, kb_name=kb_name, scope=scope, metadata=metadata)
|
|
271
261
|
|
|
272
262
|
|
|
273
263
|
@final
|
|
@@ -323,11 +313,7 @@ summarize_to_memory(content="Company guidelines...", topic="Guidelines", scope="
|
|
|
323
313
|
|
|
324
314
|
# Use the memory service to create a summary
|
|
325
315
|
# This would typically use an LLM to summarize, but for now we'll store as-is
|
|
326
|
-
summary = (
|
|
327
|
-
f"Summary of {topic}:\n{content[:500]}..."
|
|
328
|
-
if len(content) > 500
|
|
329
|
-
else content
|
|
330
|
-
)
|
|
316
|
+
summary = f"Summary of {topic}:\n{content[:500]}..." if len(content) > 500 else content
|
|
331
317
|
|
|
332
318
|
# Store the summary as a memory
|
|
333
319
|
from hanzo_memory.services.memory import get_memory_service
|
|
@@ -358,9 +344,7 @@ summarize_to_memory(content="Company guidelines...", topic="Guidelines", scope="
|
|
|
358
344
|
if auto_facts:
|
|
359
345
|
# In a real implementation, this would use LLM to extract key facts
|
|
360
346
|
# For now, we'll just note it
|
|
361
|
-
result += (
|
|
362
|
-
"\n(Auto-fact extraction would extract key facts from the summary)"
|
|
363
|
-
)
|
|
347
|
+
result += "\n(Auto-fact extraction would extract key facts from the summary)"
|
|
364
348
|
|
|
365
349
|
return result
|
|
366
350
|
|
|
@@ -377,9 +361,7 @@ summarize_to_memory(content="Company guidelines...", topic="Guidelines", scope="
|
|
|
377
361
|
scope: str = "project",
|
|
378
362
|
auto_facts: bool = True,
|
|
379
363
|
) -> str:
|
|
380
|
-
return await tool_self.call(
|
|
381
|
-
ctx, content=content, topic=topic, scope=scope, auto_facts=auto_facts
|
|
382
|
-
)
|
|
364
|
+
return await tool_self.call(ctx, content=content, topic=topic, scope=scope, auto_facts=auto_facts)
|
|
383
365
|
|
|
384
366
|
|
|
385
367
|
@final
|
|
@@ -21,7 +21,7 @@ try:
|
|
|
21
21
|
except ImportError:
|
|
22
22
|
MEMORY_AVAILABLE = False
|
|
23
23
|
raise ImportError(
|
|
24
|
-
"hanzo-memory package is required for memory tools. Install it from ~/work/hanzo/
|
|
24
|
+
"hanzo-memory package is required for memory tools. Install it from ~/work/hanzo/python-sdk/pkg/hanzo-memory"
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
|
|
@@ -127,9 +127,7 @@ recall_memories(queries=["coding standards"], scope="global")
|
|
|
127
127
|
tool_self = self
|
|
128
128
|
|
|
129
129
|
@mcp_server.tool(name=self.name, description=self.description)
|
|
130
|
-
async def recall_memories(
|
|
131
|
-
ctx: MCPContext, queries: List[str], limit: int = 10, scope: str = "project"
|
|
132
|
-
) -> str:
|
|
130
|
+
async def recall_memories(ctx: MCPContext, queries: List[str], limit: int = 10, scope: str = "project") -> str:
|
|
133
131
|
return await tool_self.call(ctx, queries=queries, limit=limit, scope=scope)
|
|
134
132
|
|
|
135
133
|
|
|
@@ -247,9 +245,7 @@ update_memories(updates=[
|
|
|
247
245
|
# The hanzo-memory service doesn't have update implemented yet
|
|
248
246
|
# When it's implemented, we would call:
|
|
249
247
|
# success = self.service.update_memory(self.user_id, memory_id, content=statement)
|
|
250
|
-
await tool_ctx.warning(
|
|
251
|
-
f"Memory update not fully implemented in hanzo-memory yet: {memory_id}"
|
|
252
|
-
)
|
|
248
|
+
await tool_ctx.warning(f"Memory update not fully implemented in hanzo-memory yet: {memory_id}")
|
|
253
249
|
success_count += 1
|
|
254
250
|
|
|
255
251
|
return f"Would update {success_count} of {len(updates)} memories (update not fully implemented in hanzo-memory yet)."
|
|
@@ -260,9 +256,7 @@ update_memories(updates=[
|
|
|
260
256
|
tool_self = self
|
|
261
257
|
|
|
262
258
|
@mcp_server.tool(name=self.name, description=self.description)
|
|
263
|
-
async def update_memories(
|
|
264
|
-
ctx: MCPContext, updates: List[Dict[str, str]]
|
|
265
|
-
) -> str:
|
|
259
|
+
async def update_memories(ctx: MCPContext, updates: List[Dict[str, str]]) -> str:
|
|
266
260
|
return await tool_self.call(ctx, updates=updates)
|
|
267
261
|
|
|
268
262
|
|
|
@@ -398,13 +392,9 @@ manage_memories(
|
|
|
398
392
|
|
|
399
393
|
if memory_id and statement:
|
|
400
394
|
# Update not fully implemented in hanzo-memory yet
|
|
401
|
-
await tool_ctx.warning(
|
|
402
|
-
f"Memory update not fully implemented: {memory_id}"
|
|
403
|
-
)
|
|
395
|
+
await tool_ctx.warning(f"Memory update not fully implemented: {memory_id}")
|
|
404
396
|
success_count += 1
|
|
405
|
-
results.append(
|
|
406
|
-
f"Would update {success_count} memories (update pending implementation)"
|
|
407
|
-
)
|
|
397
|
+
results.append(f"Would update {success_count} memories (update pending implementation)")
|
|
408
398
|
|
|
409
399
|
# Delete memories
|
|
410
400
|
if deletions:
|
|
@@ -433,6 +423,4 @@ manage_memories(
|
|
|
433
423
|
updates: Optional[List[Dict[str, str]]] = None,
|
|
434
424
|
deletions: Optional[List[str]] = None,
|
|
435
425
|
) -> str:
|
|
436
|
-
return await tool_self.call(
|
|
437
|
-
ctx, creations=creations, updates=updates, deletions=deletions
|
|
438
|
-
)
|
|
426
|
+
return await tool_self.call(ctx, creations=creations, updates=updates, deletions=deletions)
|
|
@@ -257,9 +257,7 @@ class FindTool(BaseTool):
|
|
|
257
257
|
# Resolve path
|
|
258
258
|
root_path = Path(path).resolve()
|
|
259
259
|
if not root_path.exists():
|
|
260
|
-
return MCPResourceDocument(
|
|
261
|
-
data={"error": f"Path does not exist: {path}", "results": []}
|
|
262
|
-
)
|
|
260
|
+
return MCPResourceDocument(data={"error": f"Path does not exist: {path}", "results": []})
|
|
263
261
|
|
|
264
262
|
# Get ignore patterns
|
|
265
263
|
ignore_patterns = set()
|
|
@@ -270,9 +268,7 @@ class FindTool(BaseTool):
|
|
|
270
268
|
min_size_bytes = self._parse_size(min_size) if min_size else None
|
|
271
269
|
max_size_bytes = self._parse_size(max_size) if max_size else None
|
|
272
270
|
modified_after_ts = self._parse_time(modified_after) if modified_after else None
|
|
273
|
-
modified_before_ts = (
|
|
274
|
-
self._parse_time(modified_before) if modified_before else None
|
|
275
|
-
)
|
|
271
|
+
modified_before_ts = self._parse_time(modified_before) if modified_before else None
|
|
276
272
|
|
|
277
273
|
# Collect matches
|
|
278
274
|
matches = []
|
|
@@ -350,20 +346,14 @@ class FindTool(BaseTool):
|
|
|
350
346
|
stats = {
|
|
351
347
|
"total_found": total_results,
|
|
352
348
|
"search_time_ms": int((time.time() - start_time) * 1000),
|
|
353
|
-
"search_method": (
|
|
354
|
-
"ffind" if FFIND_AVAILABLE and not in_content else "python"
|
|
355
|
-
),
|
|
349
|
+
"search_method": ("ffind" if FFIND_AVAILABLE and not in_content else "python"),
|
|
356
350
|
"root_path": str(root_path),
|
|
357
351
|
"filters_applied": {
|
|
358
352
|
"pattern": pattern,
|
|
359
353
|
"type": type,
|
|
360
|
-
"size": (
|
|
361
|
-
{"min": min_size, "max": max_size} if min_size or max_size else None
|
|
362
|
-
),
|
|
354
|
+
"size": ({"min": min_size, "max": max_size} if min_size or max_size else None),
|
|
363
355
|
"modified": (
|
|
364
|
-
{"after": modified_after, "before": modified_before}
|
|
365
|
-
if modified_after or modified_before
|
|
366
|
-
else None
|
|
356
|
+
{"after": modified_after, "before": modified_before} if modified_after or modified_before else None
|
|
367
357
|
),
|
|
368
358
|
"max_depth": max_depth,
|
|
369
359
|
"gitignore": respect_gitignore,
|
|
@@ -594,9 +584,7 @@ class FindTool(BaseTool):
|
|
|
594
584
|
elif fuzzy:
|
|
595
585
|
pattern_lower = pattern.lower() if not case_sensitive else pattern
|
|
596
586
|
matcher = (
|
|
597
|
-
lambda name: SequenceMatcher(
|
|
598
|
-
None, pattern_lower, name.lower() if not case_sensitive else name
|
|
599
|
-
).ratio()
|
|
587
|
+
lambda name: SequenceMatcher(None, pattern_lower, name.lower() if not case_sensitive else name).ratio()
|
|
600
588
|
> 0.6
|
|
601
589
|
)
|
|
602
590
|
else:
|
|
@@ -608,9 +596,7 @@ class FindTool(BaseTool):
|
|
|
608
596
|
matcher = lambda name: fnmatch.fnmatch(name, pattern)
|
|
609
597
|
|
|
610
598
|
# Walk directory tree
|
|
611
|
-
for dirpath, dirnames, filenames in os.walk(
|
|
612
|
-
str(root), followlinks=follow_symlinks
|
|
613
|
-
):
|
|
599
|
+
for dirpath, dirnames, filenames in os.walk(str(root), followlinks=follow_symlinks):
|
|
614
600
|
# Check depth
|
|
615
601
|
if max_depth is not None:
|
|
616
602
|
depth = len(Path(dirpath).relative_to(root).parts)
|
|
@@ -621,11 +607,7 @@ class FindTool(BaseTool):
|
|
|
621
607
|
# Filter directories to skip
|
|
622
608
|
if respect_gitignore:
|
|
623
609
|
dirnames[:] = [
|
|
624
|
-
d
|
|
625
|
-
for d in dirnames
|
|
626
|
-
if not self._should_ignore(
|
|
627
|
-
os.path.join(dirpath, d), ignore_patterns
|
|
628
|
-
)
|
|
610
|
+
d for d in dirnames if not self._should_ignore(os.path.join(dirpath, d), ignore_patterns)
|
|
629
611
|
]
|
|
630
612
|
|
|
631
613
|
# Check directories
|
|
@@ -662,9 +644,7 @@ class FindTool(BaseTool):
|
|
|
662
644
|
match_found = True
|
|
663
645
|
elif in_content:
|
|
664
646
|
# Search in file content
|
|
665
|
-
match_found = await self._search_in_file(
|
|
666
|
-
full_path, pattern, case_sensitive
|
|
667
|
-
)
|
|
647
|
+
match_found = await self._search_in_file(full_path, pattern, case_sensitive)
|
|
668
648
|
else:
|
|
669
649
|
match_found = False
|
|
670
650
|
|
|
@@ -686,9 +666,7 @@ class FindTool(BaseTool):
|
|
|
686
666
|
|
|
687
667
|
return matches
|
|
688
668
|
|
|
689
|
-
async def _search_in_file(
|
|
690
|
-
self, file_path: str, pattern: str, case_sensitive: bool
|
|
691
|
-
) -> bool:
|
|
669
|
+
async def _search_in_file(self, file_path: str, pattern: str, case_sensitive: bool) -> bool:
|
|
692
670
|
"""Search for pattern in file content."""
|
|
693
671
|
try:
|
|
694
672
|
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
|