Skip to content

Commit 3568c46

Browse files
committed
samples: improve dynamic server with params descriptions
1 parent 35a87e8 commit 3568c46

File tree

3 files changed

+66
-20
lines changed

3 files changed

+66
-20
lines changed

samples/mcp-dynamic-server/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "mcp-dynamic-server"
3-
version = "0.0.3"
3+
version = "0.0.5"
44
description = "Dynamic tools MCP Server"
55
authors = [{ name = "John Doe" }]
66
dependencies = [

samples/mcp-dynamic-server/server.py

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,43 @@
55
# Initialize the MCP server
66
mcp = 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
1032
class 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 {

samples/mcp-dynamic-server/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)