55# Initialize the MCP server
66mcp = FastMCP ("Self-Extending MCP Server" )
77
8+ built_in_tools = {
9+ "get_tools" : {
10+ "description" : "Get a list of all available tools in the MCP server." ,
11+ "parameters" : {}
12+ },
13+ "add_tool" : {
14+ "description" : "Add a new tool to the MCP server." ,
15+ "parameters" : {
16+ "name" : "Name of the tool" ,
17+ "code" : "Python code implementing the tool function" ,
18+ "description" : "Description of what the tool does" ,
19+ "param_descriptions" : "Dictionary of parameter names to descriptions (optional)"
20+ }
21+ },
22+ "call_tool" : {
23+ "description" : "Call a registered tool with the given arguments." ,
24+ "parameters" : {
25+ "name" : "Name of the tool to call" ,
26+ "args" : "Dictionary of arguments to pass to the tool"
27+ }
28+ }
29+ }
830
931# Tool registry to track dynamically added tools
1032class ToolRegistry :
1133 def __init__ (self ):
1234 self .tools = {} # name -> function
1335 self .metadata = {} # name -> metadata
1436
15- def register (self , name : str , func : Callable , description : str ):
37+ def register (self , name : str , func : Callable , description : str , param_descriptions : Dict [ str , str ] = None ):
1638 """Register a new tool in the registry."""
1739 self .tools [name ] = func
18- self .metadata [name ] = {"name" : name , "description" : description }
40+ self .metadata [name ] = {
41+ "name" : name ,
42+ "description" : description ,
43+ "parameters" : param_descriptions or {}
44+ }
1945
2046 def get_tool (self , name : str ) -> Optional [Callable ]:
2147 """Get a tool by name."""
@@ -49,19 +75,23 @@ def get_tools() -> Dict[str, Any]:
4975 try :
5076 tools = registry .list_tools ()
5177
52- # Add the built-in tools
53- built_in_tools = ["get_tools" , "add_tool" , "call_tool" ]
54-
5578 # Combine built-in tools with dynamic tools
56- all_tools = [{"name" : tool , "built_in" : True } for tool in built_in_tools ]
79+ all_tools = []
80+ for name , info in built_in_tools .items ():
81+ all_tools .append ({
82+ "name" : name ,
83+ "description" : info ["description" ],
84+ "parameters" : info ["parameters" ],
85+ "built_in" : True
86+ })
87+
5788 for tool in tools :
58- all_tools .append (
59- {
60- "name" : tool ["name" ],
61- "description" : tool ["description" ],
62- "built_in" : False ,
63- }
64- )
89+ all_tools .append ({
90+ "name" : tool ["name" ],
91+ "description" : tool ["description" ],
92+ "parameters" : tool ["parameters" ],
93+ "built_in" : False
94+ })
6595
6696 return {"status" : "success" , "tools" : all_tools }
6797 except Exception as e :
@@ -70,13 +100,14 @@ def get_tools() -> Dict[str, Any]:
70100
71101# Core functionality: Add a new tool
72102@mcp .tool ()
73- def add_tool (name : str , code : str , description : str ) -> Dict [str , Any ]:
103+ def add_tool (name : str , code : str , description : str , param_descriptions : Dict [ str , str ] = None ) -> Dict [str , Any ]:
74104 """Add a new tool to the MCP server.
75105
76106 Args:
77107 name: Name of the tool
78108 code: Python code implementing the tool function
79109 description: Description of what the tool does
110+ param_descriptions: Dictionary of parameter names to descriptions
80111
81112 Returns:
82113 Dictionary with operation status
@@ -109,9 +140,16 @@ def add_tool(name: str, code: str, description: str) -> Dict[str, Any]:
109140 }
110141
111142 # Register the tool with our registry
112- registry .register (name , func , description )
143+ registry .register (name , func , description , param_descriptions )
113144
114- return {"status" : "success" , "message" : f"Tool '{ name } ' added successfully" }
145+ # Get the parameter information to return
146+ params = registry .get_metadata (name )["parameters" ]
147+
148+ return {
149+ "status" : "success" ,
150+ "message" : f"Tool '{ name } ' added successfully" ,
151+ "parameters" : params
152+ }
115153
116154 except SyntaxError as e :
117155 return {
@@ -139,27 +177,35 @@ def call_tool(name: str, args: Dict[str, Any]) -> Dict[str, Any]:
139177 """
140178 try :
141179 # Check if it's a built-in tool
142- if name in [ "get_tools" , "add_tool" , "call_tool" ] :
180+ if name in built_in_tools :
143181 return {
144182 "status" : "error" ,
145183 "message" : f"Cannot call built-in tool '{ name } ' using call_tool" ,
184+ "note" : f"Use the { name } function directly instead of call_tool" ,
185+ "parameters" : built_in_tools [name ]["parameters" ]
146186 }
147187
148188 # Get the tool
149189 tool = registry .get_tool (name )
150190
151191 if not tool :
152- return {"status" : "error" , "message" : f"Tool '{ name } ' not found" }
192+ return {
193+ "status" : "error" ,
194+ "message" : f"Tool '{ name } ' not found" ,
195+ "available_tools" : [t ["name" ] for t in registry .list_tools ()]
196+ }
153197
154198 # Call the tool with the provided arguments
155199 try :
156200 result = tool (** args )
157201 return result
158202 except TypeError as e :
159203 # Likely an argument mismatch
204+ params = registry .get_metadata (name )["parameters" ]
160205 return {
161206 "status" : "error" ,
162207 "message" : f"Argument error calling tool '{ name } ': { str (e )} " ,
208+ "expected_parameters" : params
163209 }
164210 except Exception as e :
165211 return {
0 commit comments