Skip to content

Commit ec73be7

Browse files
committed
refactor: add type annotations and improve backend adapter handling in mcpify/wrapper.py
1 parent c180400 commit ec73be7

File tree

1 file changed

+25
-15
lines changed

1 file changed

+25
-15
lines changed

mcpify/wrapper.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from mcp.server.fastmcp import FastMCP
1515

16-
from .backend import create_adapter
16+
from .backend import BackendAdapter, create_adapter
1717

1818

1919
class MCPWrapper:
@@ -28,6 +28,7 @@ def __init__(self, config_path: str):
2828
self.mcp = FastMCP(server_name)
2929

3030
# Check if backend configuration exists
31+
self.adapter: BackendAdapter | None = None
3132
if "backend" in self.config:
3233
self.adapter = create_adapter(self.config["backend"])
3334
else:
@@ -54,18 +55,19 @@ def create_tool_function(self, tool_config: dict[str, Any]) -> Callable:
5455
tool_name = tool_config["name"]
5556
parameters = tool_config.get("parameters", [])
5657

57-
def tool_executor(**kwargs):
58+
def tool_executor(**kwargs: Any) -> Any:
5859
"""Generic function to execute tools"""
5960
if self.adapter:
6061
# Use adapter to execute tool
61-
def run_async_in_thread():
62+
def run_async_in_thread() -> Any:
6263
"""Run async code in new thread"""
6364
loop = asyncio.new_event_loop()
6465
asyncio.set_event_loop(loop)
6566
try:
66-
return loop.run_until_complete(
67-
self.adapter.execute_tool(tool_config, kwargs)
68-
)
67+
if self.adapter is not None:
68+
return loop.run_until_complete(
69+
self.adapter.execute_tool(tool_config, kwargs)
70+
)
6971
finally:
7072
loop.close()
7173

@@ -86,8 +88,7 @@ def run_async_in_thread():
8688
# Check if we have args specified in the tool config
8789
if not args_template:
8890
return (
89-
"Error: No backend adapter configured and no command "
90-
"specified"
91+
"Error: No backend adapter configured and no command specified"
9192
)
9293

9394
cmd_args = []
@@ -136,15 +137,24 @@ def run_async_in_thread():
136137

137138
# Create new function signature
138139
new_signature = inspect.Signature(sig_params)
139-
tool_executor.__signature__ = new_signature
140+
141+
# Dynamically assign the generated signature.
142+
# Normally we would assign via tool_executor.__signature__ = new_signature.
143+
# However, since __signature__ is not a known attribute of FunctionType,
144+
# directly assigning it would cause mypy to report an "attribute not defined" error.
145+
#
146+
# Using tool_executor.__dict__["__signature__"] = new_signature
147+
# bypasses the static type checker, as mypy does not analyze __dict__ content.
148+
# This allows us to safely inject the runtime signature without triggering type errors.
149+
tool_executor.__dict__["__signature__"] = new_signature
140150
else:
141151
# Function with no parameters
142152
tool_executor.__annotations__ = {"return": str}
143-
tool_executor.__signature__ = inspect.Signature([])
153+
tool_executor.__dict__["__signature__"] = inspect.Signature([])
144154

145155
return tool_executor
146156

147-
def _register_tools(self):
157+
def _register_tools(self) -> None:
148158
"""Register all tools to MCP server"""
149159
for tool in self.config.get("tools", []):
150160
tool_name = tool["name"]
@@ -156,21 +166,21 @@ def _register_tools(self):
156166
# Register to MCP
157167
self.mcp.tool(name=tool_name, description=tool_description)(tool_func)
158168

159-
async def start_backend(self):
169+
async def start_backend(self) -> None:
160170
"""Start backend service"""
161171
if self.adapter:
162172
await self.adapter.start()
163173

164-
async def stop_backend(self):
174+
async def stop_backend(self) -> None:
165175
"""Stop backend service"""
166176
if self.adapter:
167177
await self.adapter.stop()
168178

169-
def server(self):
179+
def server(self) -> FastMCP:
170180
"""Run MCP server"""
171181
return self.mcp
172182

173-
def run(self):
183+
def run(self) -> None:
174184
"""Start MCP server"""
175185
# If adapter exists, start backend service first
176186
if self.adapter:

0 commit comments

Comments
 (0)