Jeremiah Lowin commited on
Commit
fc79ef8
·
unverified ·
2 Parent(s): 80b9b2c2547093

Merge pull request #14 from jlowin/refactor

Browse files
src/fastmcp/resources/__init__.py CHANGED
@@ -8,7 +8,7 @@ from .types import (
8
  DirectoryResource,
9
  )
10
  from .templates import ResourceTemplate
11
- from .manager import ResourceManager
12
 
13
  __all__ = [
14
  "Resource",
 
8
  DirectoryResource,
9
  )
10
  from .templates import ResourceTemplate
11
+ from .resource_manager import ResourceManager
12
 
13
  __all__ = [
14
  "Resource",
src/fastmcp/resources/{manager.py → resource_manager.py} RENAMED
File without changes
src/fastmcp/server.py CHANGED
@@ -29,8 +29,7 @@ from pydantic_settings import BaseSettings
29
  from pydantic.networks import _BaseUrl
30
 
31
  from fastmcp.exceptions import ResourceError
32
- from fastmcp.resources import Resource, ResourceManager
33
- from fastmcp.resources.types import FunctionResource
34
  from fastmcp.tools import ToolManager
35
  from fastmcp.utilities.logging import configure_logging
36
  from fastmcp.utilities.types import Image
 
29
  from pydantic.networks import _BaseUrl
30
 
31
  from fastmcp.exceptions import ResourceError
32
+ from fastmcp.resources import Resource, ResourceManager, FunctionResource
 
33
  from fastmcp.tools import ToolManager
34
  from fastmcp.utilities.logging import configure_logging
35
  from fastmcp.utilities.types import Image
src/fastmcp/tools/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from .base import Tool
2
+ from .tool_manager import ToolManager
3
+
4
+ __all__ = ["Tool", "ToolManager"]
src/fastmcp/{tools.py → tools/base.py} RENAMED
@@ -1,19 +1,16 @@
1
- """Tool management for FastMCP."""
 
2
 
3
- import inspect
4
- from typing import Any, Callable, Dict, Optional, TYPE_CHECKING
5
 
6
  from pydantic import BaseModel, Field, TypeAdapter, validate_call
7
 
8
- from .exceptions import ToolError
9
- from .utilities.logging import get_logger
10
- import fastmcp
11
 
12
  if TYPE_CHECKING:
13
  from fastmcp.server import Context
14
 
15
- logger = get_logger(__name__)
16
-
17
 
18
  class Tool(BaseModel):
19
  """Internal tool registration info."""
@@ -80,45 +77,3 @@ class Tool(BaseModel):
80
  return self.func(**arguments)
81
  except Exception as e:
82
  raise ToolError(f"Error executing tool {self.name}: {e}") from e
83
-
84
-
85
- class ToolManager:
86
- """Manages FastMCP tools."""
87
-
88
- def __init__(self, warn_on_duplicate_tools: bool = True):
89
- self._tools: Dict[str, Tool] = {}
90
- self.warn_on_duplicate_tools = warn_on_duplicate_tools
91
-
92
- def get_tool(self, name: str) -> Optional[Tool]:
93
- """Get tool by name."""
94
- return self._tools.get(name)
95
-
96
- def list_tools(self) -> list[Tool]:
97
- """List all registered tools."""
98
- return list(self._tools.values())
99
-
100
- def add_tool(
101
- self,
102
- func: Callable,
103
- name: Optional[str] = None,
104
- description: Optional[str] = None,
105
- ) -> Tool:
106
- """Add a tool to the server."""
107
- tool = Tool.from_function(func, name=name, description=description)
108
- existing = self._tools.get(tool.name)
109
- if existing:
110
- if self.warn_on_duplicate_tools:
111
- logger.warning(f"Tool already exists: {tool.name}")
112
- return existing
113
- self._tools[tool.name] = tool
114
- return tool
115
-
116
- async def call_tool(
117
- self, name: str, arguments: dict, context: Optional["Context"] = None
118
- ) -> Any:
119
- """Call a tool by name with arguments."""
120
- tool = self.get_tool(name)
121
- if not tool:
122
- raise ToolError(f"Unknown tool: {name}")
123
-
124
- return await tool.run(arguments, context=context)
 
1
+ import fastmcp
2
+ from fastmcp.exceptions import ToolError
3
 
 
 
4
 
5
  from pydantic import BaseModel, Field, TypeAdapter, validate_call
6
 
7
+
8
+ import inspect
9
+ from typing import TYPE_CHECKING, Any, Callable, Optional
10
 
11
  if TYPE_CHECKING:
12
  from fastmcp.server import Context
13
 
 
 
14
 
15
  class Tool(BaseModel):
16
  """Internal tool registration info."""
 
77
  return self.func(**arguments)
78
  except Exception as e:
79
  raise ToolError(f"Error executing tool {self.name}: {e}") from e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/fastmcp/tools/tool_manager.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastmcp.exceptions import ToolError
2
+
3
+ from fastmcp.tools.base import Tool
4
+
5
+
6
+ from typing import Any, Callable, Dict, Optional, TYPE_CHECKING
7
+
8
+ from fastmcp.utilities.logging import get_logger
9
+
10
+ if TYPE_CHECKING:
11
+ from fastmcp.server import Context
12
+
13
+ logger = get_logger(__name__)
14
+
15
+
16
+ class ToolManager:
17
+ """Manages FastMCP tools."""
18
+
19
+ def __init__(self, warn_on_duplicate_tools: bool = True):
20
+ self._tools: Dict[str, Tool] = {}
21
+ self.warn_on_duplicate_tools = warn_on_duplicate_tools
22
+
23
+ def get_tool(self, name: str) -> Optional[Tool]:
24
+ """Get tool by name."""
25
+ return self._tools.get(name)
26
+
27
+ def list_tools(self) -> list[Tool]:
28
+ """List all registered tools."""
29
+ return list(self._tools.values())
30
+
31
+ def add_tool(
32
+ self,
33
+ func: Callable,
34
+ name: Optional[str] = None,
35
+ description: Optional[str] = None,
36
+ ) -> Tool:
37
+ """Add a tool to the server."""
38
+ tool = Tool.from_function(func, name=name, description=description)
39
+ existing = self._tools.get(tool.name)
40
+ if existing:
41
+ if self.warn_on_duplicate_tools:
42
+ logger.warning(f"Tool already exists: {tool.name}")
43
+ return existing
44
+ self._tools[tool.name] = tool
45
+ return tool
46
+
47
+ async def call_tool(
48
+ self, name: str, arguments: dict, context: Optional["Context"] = None
49
+ ) -> Any:
50
+ """Call a tool by name with arguments."""
51
+ tool = self.get_tool(name)
52
+ if not tool:
53
+ raise ToolError(f"Unknown tool: {name}")
54
+
55
+ return await tool.run(arguments, context=context)