fix(mcp): stop logging tool-call input in MCP client (#31393)

Backport of #31393 to stable/1.90.x.
Cherry-picked from 7acc0157df (litellm_internal_staging).

The test-file conflict hunk also carried the staging-only TestMCPClientResolvedAuth
class from an unrelated commit that never reached this line; it was dropped and only
the additions belonging to #31393 were kept.
This commit is contained in:
ryan-crabbe-berri 2026-07-02 21:41:21 -07:00 committed by mateo-berri
parent bb90565092
commit bb77cc0841
2 changed files with 48 additions and 2 deletions

View file

@ -555,7 +555,7 @@ class MCPClient:
Call an MCP Tool.
"""
verbose_logger.info(
f"MCP client calling tool '{call_tool_request_params.name}' with arguments: {call_tool_request_params.arguments}"
f"MCP client calling tool '{call_tool_request_params.name}'"
)
async def on_progress(
@ -664,7 +664,7 @@ class MCPClient:
) -> GetPromptResult:
"""Fetch a prompt definition from the MCP server."""
verbose_logger.info(
f"MCP client fetching prompt '{get_prompt_request_params.name}' with arguments: {get_prompt_request_params.arguments}"
f"MCP client fetching prompt '{get_prompt_request_params.name}'"
)
async def _get_prompt_operation(session: ClientSession):

View file

@ -543,5 +543,51 @@ class TestExecuteSessionOperationSurfacesTransportError:
assert result == "done"
def _all_logged_messages(mock_logger):
return " ".join(
str(call.args[0])
for level in ("info", "debug", "warning", "error", "exception")
for call in getattr(mock_logger, level).call_args_list
if call.args
)
@pytest.mark.asyncio
async def test_call_tool_does_not_log_arguments():
from mcp.types import CallToolRequestParams
secret = "ssn-123-45-6789"
client = MCPClient(server_url="http://test-server")
client.run_with_session = AsyncMock(return_value=MagicMock())
params = CallToolRequestParams(
name="search_tool", arguments={"input": secret, "model": "gpt-5-mini"}
)
with patch.object(mcp_client_module, "verbose_logger") as mock_logger:
await client.call_tool(params)
logged = _all_logged_messages(mock_logger)
assert "search_tool" in logged
assert secret not in logged
assert "gpt-5-mini" not in logged
@pytest.mark.asyncio
async def test_get_prompt_does_not_log_arguments():
from mcp.types import GetPromptRequestParams
secret = "ssn-987-65-4321"
client = MCPClient(server_url="http://test-server")
client.run_with_session = AsyncMock(return_value=MagicMock())
params = GetPromptRequestParams(name="my_prompt", arguments={"input": secret})
with patch.object(mcp_client_module, "verbose_logger") as mock_logger:
await client.get_prompt(params)
logged = _all_logged_messages(mock_logger)
assert "my_prompt" in logged
assert secret not in logged
if __name__ == "__main__":
pytest.main([__file__])