Google's ADK Bug Report: Finding and Patching a Bug With Reserved Keywords
This is Part 2 of a series on building agents with Google's Agent Development Kit (ADK). See here for Part 1.
We were testing our AI agent built with Google's Agent Development Kit (ADK) when we discovered a critical bug. The agent was calling MCP tools with the wrong parameter names—and failing silently.
This bug happens when an MCP tool has a parameter that's a Python reserved keyword (like from, class, or import).
ADK automatically renames these parameters to avoid syntax errors, but never tells the MCP server about the change.
Here's what we found, why it matters, and how to fix it.
The Bug: Silent Parameter Renaming
from → from1_)
to avoid syntax errors. But it sends the renamed parameters to the MCP server, which expects the original names. The result?
Silent failures where your agent thinks it called the tool correctly, but the server rejects the request.
The Scenario
We built a Weather-to-SMS agent that:
- Converts a location name to latitude/longitude (geocoding MCP)
- Fetches weather for those coordinates (weather MCP)
- Sends an SMS with the weather summary (Twilio MCP)
The Twilio MCP's send_message tool expects these parameters:
@mcp.tool()
def send_message(from: str, to: str, body: str, media_url: str = None) -> dict:
"""Send an SMS message via Twilio"""
# from = sender's phone number
# to = recipient's phone number
# body = message content
# media_url = optional URL for MMS media attachment
...
Notice the problem? from is a Python reserved keyword. You can't use it as a variable name without causing syntax errors.
What ADK Does
Google's ADK detects reserved keywords and automatically renames them. In this case:
from→from1_class→class_import→import_
This prevents Python syntax errors when the agent calls the tool. So far, so good.
The Problem
ADK sends the renamed parameters to the MCP server:
{
"method": "tools/call",
"params": {
"name": "send_message",
"arguments": {
"from1_": "9876543210", // ❌ Wrong parameter name
"to": "012345679",
"body": "Weather in DC: 2.1°C and clear"
}
}
}
But the MCP server expects:
{
"method": "tools/call",
"params": {
"name": "send_message",
"arguments": {
"from": "9876543210", // ✅ Correct parameter name
"to": "012345679",
"body": "Weather in DC: 2.1°C and clear"
}
}
}
The server doesn't recognize from1_ as a valid parameter. It either:
- Rejects the request with an error
- Uses a default value (if the parameter is optional)
- Silently fails
Your agent has no idea anything went wrong.
Why This is Critical
This isn't a theoretical edge case. It affects any MCP tool with reserved keyword parameters:
- Messaging APIs: Twilio, SendGrid, Slack (all use
from) - Email APIs: Gmail, Outlook (use
from,to,subject) - File operations: Tools using
import,class,type - Any API mirroring Python syntax:
for,if,while, etc.
Without systematic testing, you won't discover this until:
- Your agent deploys to production and fails
- Users report that messages aren't being sent
- You manually inspect the tool calls (which most developers never do)
How We Discovered It
We were testing our agent with Simvasia, which lets you create mocks of MCP servers to test agents without side effects.
While inspecting the actual tool calls being made, we noticed:
functionCall:
id: "adk-fbd8152b-4a41-47bc-abd9-2ec30de4688b"
args:
body: "The current weather in Washington, DC is 2.1°C and clear."
from1_: "9876543210" // ❌ This should be "from"
to: "012345679"
name: "send_message"
The parameter was from1_ instead of from. The Twilio MCP server rejected the request for missing the required input parameter from.
This is exactly why you need systematic testing. Without mocking and inspecting tool calls, we would never have caught this bug before production.
The Solution: Using before_tool_callback
ADK provides a powerful hook called before_tool_callback that's called just before a tool executes.
We can use this to intercept and remap the parameters before they're sent to the MCP server:
from google.adk.tools.base_tool import BaseTool
from google.adk.tools.tool_context import ToolContext
from typing import Any, Dict, Optional
def parameter_remapping_callback(
tool: BaseTool, args: Dict[str, Any], tool_context: ToolContext
) -> Optional[Dict]:
"""
Before tool callback that remaps reserved keyword parameters.
ADK renames 'from' -> 'from1_' to avoid Python keyword conflicts.
This callback remaps it back to 'from' before calling the MCP server.
"""
# Check if this is the send_message tool that needs parameter remapping
if tool.name == "send_message" and "from1_" in args:
print(f"[Callback] Detected 'from1_' parameter. Remapping to 'from'.")
print(f"[Callback] Original args: {args}")
# Remap from1_ back to from
args["from"] = args.pop("from1_")
print(f"[Callback] Remapped args: {args}")
# Return None to proceed with (potentially modified) args
return None
How to Use It
Pass the callback function to your agent via the before_tool_callback parameter:
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPServerParams
sms_agent = Agent(
model="gemini-2.5-flash",
name="sms_agent",
tools=[
McpToolset(
connection_params=StreamableHTTPServerParams(
url="https://www.simvasia.com/sandbox/simvasia/twilio_mcp/",
headers={"X-Sandbox-Token": "SIMVASIA_TOKEN"},
),
),
],
# Use before_tool_callback to remap 'from1_' back to 'from'
before_tool_callback=parameter_remapping_callback,
)
Result: The callback intercepts the tool call, detects from1_, remaps it to from,
and then the MCP server receives the correct parameter. The tool call succeeds! ✅
Common Reserved Keywords to Watch For
If your MCP tools use any of these Python reserved keywords as parameter names, you'll need to remap them:
False await else import pass
None break except in raise
True class finally is return
and continue for lambda try
as def from nonlocal while
assert del global not with
async elif if or yield
ADK will rename these to avoid syntax errors:
from→from1_class→class_import→import_for→for_if→if_
Use ParameterRemappingToolset with the appropriate mapping to fix it.
Key Takeaways
- ADK silently renames reserved keywords:
frombecomesfrom1_, breaking MCP calls - This affects real-world APIs: Twilio, SendGrid, Gmail, Slack, and more
- Testing reveals the bug: Without inspecting tool calls, you won't find it until production
- Use before_tool_callback: ADK's hook to intercept and fix parameter names before MCP calls
- Systematic testing is critical: Mocking tools like Simvasia let you catch these issues early
Next Steps
ADK should:
- Restore original parameters for external operations (handle reserved keywords specially internally)
- Warn developers when renaming happens
- Provide a built-in parameter mapping mechanism
- Document this behavior clearly
Until Google fixes this, use before_tool_callback as a workaround.
The difference between an agent that works in demos and one that works in production is catching bugs like this before they matter.