"""Built-in tool to hot-reload user tools and context providers without restarting."""
from navi.config import settings
from .base import Tool, ToolResult
class ReloadToolsTool(Tool):
name = "reload_tools"
description = (
"Hot-reload all tools from the tools/ directory, context providers from "
"context_providers/, and reconnect all configured MCP servers without "
"restarting the server. Call this after writing or editing a tool, context "
"provider, or MCP server configuration. Returns a report of what was loaded "
"and any errors per file or server."
)
parameters = {
"type": "object",
"properties": {},
"required": [],
}
def __init__(self, registry=None, cp_registry=None, mcp_manager=None) -> None:
self._registry = registry
self._cp_registry = cp_registry
self._mcp_manager = mcp_manager
async def execute(self, params: dict) -> ToolResult:
if self._registry is None:
return ToolResult(success=False, output="Tool registry not available.", error="no_registry")
lines = []
has_errors = False
tool_result = self._registry.reload_user_tools(settings.tools_dir)
if tool_result.loaded:
lines.append(f"Tools ({len(tool_result.loaded)}): {', '.join(t.name for t in tool_result.loaded)}")
else:
lines.append("Tools: none.")
if tool_result.errors:
has_errors = True
lines.append(f"Tool errors ({len(tool_result.errors)}):")
for filename, error in tool_result.errors.items():
lines.append(f" {filename}: {error}")
if self._cp_registry is not None:
cp_result = self._cp_registry.reload_user_providers(settings.context_providers_dir)
if cp_result.loaded:
lines.append(f"Context providers ({len(cp_result.loaded)}): {', '.join(cp_result.loaded)}")
else:
lines.append("Context providers: none.")
if cp_result.errors:
has_errors = True
lines.append(f"Context provider errors ({len(cp_result.errors)}):")
for filename, error in cp_result.errors.items():
lines.append(f" {filename}: {error}")
# Reconnect MCP servers
if self._mcp_manager is not None:
try:
await self._mcp_manager.reload_all()
from navi.api.deps import register_mcp_tools
await register_mcp_tools(self._registry, self._mcp_manager)
mcp_tools = [t.name for t in self._registry.all() if t.name.startswith("mcp_")]
lines.append(f"MCP tools ({len(mcp_tools)}): {', '.join(mcp_tools) or 'none'}")
except Exception as exc:
has_errors = True
lines.append(f"MCP reload error: {exc}")
return ToolResult(success=not has_errors, output="\n".join(lines))