From 18d95262df121f45d624bd5f4c846bc33a535322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Fenal?= Date: Mon, 23 Feb 2026 18:42:16 +0100 Subject: [PATCH] fix: use functools.wraps to preserve function signatures in tool decorator MCP's tool calling mechanism was failing with "unexpected keyword argument 'args'" errors because the tool decorator wasn't properly preserving function signatures. This fix adds @functools.wraps to the wrapper function, which ensures that the function's name, docstring, annotations, and signature are correctly preserved for MCP's introspection. Without this fix, MCP cannot properly determine which parameters the wrapped function accepts, leading to parameter passing errors at runtime. --- src/mcp_google_sheets/server.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/mcp_google_sheets/server.py b/src/mcp_google_sheets/server.py index ecbd732..1ea4804 100644 --- a/src/mcp_google_sheets/server.py +++ b/src/mcp_google_sheets/server.py @@ -5,6 +5,7 @@ """ import base64 +import functools import os import sys from typing import List, Dict, Any, Optional, Union @@ -178,31 +179,36 @@ async def spreadsheet_lifespan(server: FastMCP) -> AsyncIterator[SpreadsheetCont def tool(annotations: Optional[ToolAnnotations] = None): """ Conditional tool decorator that only registers tools if they're enabled. - + This wrapper checks ENABLED_TOOLS configuration and only applies the @mcp.tool decorator if the tool should be enabled. If ENABLED_TOOLS is None (default), all tools are enabled. - + Args: annotations: Optional ToolAnnotations for the tool - + Returns: Decorator function """ def decorator(func): tool_name = func.__name__ - + # If no filtering is configured, or if this tool is in the enabled list if ENABLED_TOOLS is None or tool_name in ENABLED_TOOLS: + # Wrap the function using functools.wraps to preserve signature for MCP + @functools.wraps(func) + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + # Apply the mcp.tool decorator if annotations: - return mcp.tool(annotations=annotations)(func) + return mcp.tool(annotations=annotations)(wrapper) else: - return mcp.tool()(func) + return mcp.tool()(wrapper) else: # Don't register this tool - return the function undecorated return func - + return decorator