Coverage for src / mcp_server_langgraph / tools / __init__.py: 77%
49 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 00:43 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 00:43 +0000
1"""
2Tool catalog for LangGraph agent
4Provides a registry of tools that the agent can execute.
5Tools are defined using LangChain's @tool decorator for automatic schema generation.
6"""
8from typing import Any
10from langchain_core.tools import BaseTool
12from mcp_server_langgraph.core.config import Settings, settings
13from mcp_server_langgraph.tools.calculator_tools import add, calculator, divide, multiply, subtract
14from mcp_server_langgraph.tools.filesystem_tools import list_directory, read_file, search_files
15from mcp_server_langgraph.tools.search_tools import search_knowledge_base, web_search
18def get_all_tools(settings_override: Any | None = None) -> list[BaseTool]:
19 """
20 Factory function to get all tools based on settings.
22 This allows runtime configuration of tools, enabling:
23 - Multi-tenant deployments with different tool sets
24 - Dynamic enable/disable of code execution
25 - Testing with custom settings
27 Args:
28 settings_override: Optional Settings instance. If None, uses global settings.
30 Returns:
31 List of all available tools based on settings
32 """
33 # Use override settings if provided, otherwise use global settings
34 effective_settings: Settings = settings_override if settings_override is not None else settings
36 # Base tools (always available)
37 tools: list[BaseTool] = [
38 # Calculator tools
39 calculator,
40 add,
41 subtract,
42 multiply,
43 divide,
44 # Search tools
45 search_knowledge_base,
46 web_search,
47 # Filesystem tools (read-only for safety)
48 read_file,
49 list_directory,
50 search_files,
51 ]
53 # Code execution tools (conditional on configuration)
54 if effective_settings.enable_code_execution: 54 ↛ 55line 54 didn't jump to line 55 because the condition on line 54 was never true
55 try:
56 from mcp_server_langgraph.tools.code_execution_tools import execute_python
58 tools.append(execute_python)
59 except ImportError:
60 # Code execution dependencies not installed - silently skip
61 pass
63 return tools
66# Backward compatibility: ALL_TOOLS uses default settings
67# NOTE: For multi-tenant or runtime configuration, use get_all_tools(settings) instead
68ALL_TOOLS: list[BaseTool] = get_all_tools()
70# Tool groups for conditional loading
71CALCULATOR_TOOLS = [calculator, add, subtract, multiply, divide]
72SEARCH_TOOLS = [search_knowledge_base, web_search]
73FILESYSTEM_TOOLS = [read_file, list_directory, search_files]
76# Code execution tools group (conditionally loaded based on settings)
77# Returns empty list if code execution is disabled
78def _get_code_execution_tools() -> list[BaseTool]:
79 """Get code execution tools if enabled in settings"""
80 if settings.enable_code_execution: 80 ↛ 81line 80 didn't jump to line 81 because the condition on line 80 was never true
81 try:
82 from mcp_server_langgraph.tools.code_execution_tools import execute_python
84 return [execute_python]
85 except ImportError:
86 pass
87 return []
90CODE_EXECUTION_TOOLS = _get_code_execution_tools()
93def get_tools(categories: list[str] | None = None, settings_override: Any | None = None) -> list[BaseTool]:
94 """
95 Get tools by category.
97 Args:
98 categories: List of categories to include (None = all tools)
99 Options: "calculator", "search", "filesystem", "code_execution"
100 settings_override: Optional Settings instance for runtime configuration
102 Returns:
103 List of tools matching the categories
104 """
105 all_tools = get_all_tools(settings_override)
107 if categories is None:
108 return all_tools
110 tools: list[BaseTool] = []
111 category_map = {
112 "calculator": CALCULATOR_TOOLS,
113 "search": SEARCH_TOOLS,
114 "filesystem": FILESYSTEM_TOOLS,
115 }
117 for category in categories:
118 if category in category_map:
119 tools.extend(category_map[category])
120 elif category == "code_execution": 120 ↛ 122line 120 didn't jump to line 122 because the condition on line 120 was never true
121 # Dynamically include code execution tools if enabled
122 code_tools = [t for t in all_tools if t.name == "execute_python"]
123 tools.extend(code_tools)
125 return tools
128def get_tool_by_name(name: str, settings_override: Any | None = None) -> BaseTool | None:
129 """
130 Get a specific tool by name.
132 Args:
133 name: Tool name
134 settings_override: Optional Settings instance for runtime configuration
136 Returns:
137 Tool instance or None if not found
138 """
139 all_tools = get_all_tools(settings_override)
140 for tool in all_tools:
141 if tool.name == name:
142 return tool
143 return None
146__all__ = [
147 "ALL_TOOLS",
148 "CALCULATOR_TOOLS",
149 "CODE_EXECUTION_TOOLS",
150 "FILESYSTEM_TOOLS",
151 "SEARCH_TOOLS",
152 "add",
153 "calculator",
154 "divide",
155 "get_all_tools", # Factory function for runtime tool configuration
156 "get_tool_by_name",
157 "get_tools",
158 "list_directory",
159 "multiply",
160 "read_file",
161 "search_files",
162 "search_knowledge_base",
163 "subtract",
164 "web_search",
165]