Skip to content

Commit a6b1a39

Browse files
committed
fix: remove duplicate credential_key shorthand after upstream merge
Upstream merged credential_key for AuthConfig in McpToolset (commit 282db87). Remove the PR's credential_key Bearer token shorthand to avoid the duplicate parameter conflict. The same use case is covered by state_header_mapping with state_header_format.
1 parent e0ffe85 commit a6b1a39

3 files changed

Lines changed: 3 additions & 151 deletions

File tree

src/google/adk/tools/mcp_tool/mcp_toolset.py

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ def __init__(
254254
auth_credential: Optional[AuthCredential] = None,
255255
require_confirmation: Union[bool, Callable[..., bool]] = False,
256256
header_provider: Optional[HeaderProvider] = None,
257-
credential_key: Optional[str] = None,
258257
progress_callback: Optional[
259258
Union[ProgressFnT, ProgressCallbackFactory]
260259
] = None,
@@ -286,11 +285,6 @@ def __init__(
286285
Can be a single boolean or a callable to apply to all tools.
287286
header_provider: A callable that takes a ReadonlyContext and returns a
288287
dictionary of headers to be used for the MCP session.
289-
credential_key: A session state key whose value is sent as an
290-
``Authorization: Bearer <token>`` header on every MCP request. This is
291-
a convenience shorthand that internally creates a header_provider. If
292-
both ``credential_key`` and ``header_provider`` are provided, they are
293-
combined.
294288
progress_callback: Optional callback to receive progress notifications
295289
from MCP server during long-running tool execution. Can be either: - A
296290
``ProgressFnT`` callback that receives (progress, total, message). This
@@ -330,19 +324,7 @@ def __init__(
330324
self._connection_params = connection_params
331325
self._errlog = errlog
332326

333-
# Build the effective header_provider from credential_key and/or the
334-
# explicit header_provider parameter.
335-
credential_provider = (
336-
create_session_state_header_provider(state_key=credential_key)
337-
if credential_key
338-
else None
339-
)
340-
if credential_provider and header_provider:
341-
self._header_provider = create_combined_header_provider(
342-
[credential_provider, header_provider]
343-
)
344-
else:
345-
self._header_provider = credential_provider or header_provider
327+
self._header_provider = header_provider
346328
self._progress_callback = progress_callback
347329

348330
# Create the session manager that will handle the MCP connection
@@ -628,7 +610,7 @@ def from_config(
628610
else:
629611
raise ValueError("No connection params found in McpToolsetConfig.")
630612

631-
# Build header_provider from state_header_mapping and/or credential_key.
613+
# Build header_provider from state_header_mapping.
632614
providers = []
633615

634616
if mcp_toolset_config.state_header_mapping:
@@ -646,13 +628,6 @@ def from_config(
646628
for state_key, header_name in state_mapping.items()
647629
])
648630

649-
if mcp_toolset_config.credential_key:
650-
providers.append(
651-
create_session_state_header_provider(
652-
state_key=mcp_toolset_config.credential_key,
653-
)
654-
)
655-
656631
header_provider = (
657632
create_combined_header_provider(providers) if providers else None
658633
)
@@ -720,12 +695,6 @@ class McpToolsetConfig(BaseToolConfig):
720695

721696
use_mcp_resources: bool = False
722697

723-
credential_key: Optional[str] = None
724-
"""A session state key whose value is sent as an ``Authorization: Bearer``
725-
header on every MCP HTTP request. Convenience shorthand that is equivalent
726-
to ``state_header_mapping: {<key>: Authorization}`` with
727-
``state_header_format: {Authorization: "Bearer {value}"}``."""
728-
729698
state_header_mapping: Optional[Dict[str, str]] = None
730699
"""Maps session state keys to HTTP header names.
731700

tests/unittests/cli/test_fast_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,7 @@ async def run_async_capture(
23582358
invocation_id: Optional[str] = None,
23592359
new_message: Optional[types.Content] = None,
23602360
state_delta: Optional[dict[str, Any]] = None,
2361+
request_state: Optional[dict[str, Any]] = None,
23612362
run_config: Optional[RunConfig] = None,
23622363
):
23632364
# Capture the value of is_visual_builder inside the request context

tests/unittests/tools/mcp_tool/test_jwt_token_propagation.py

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -429,53 +429,6 @@ def test_from_config_no_state_mapping_no_provider(self):
429429
# No header provider should be created
430430
assert toolset._header_provider is None
431431

432-
def test_from_config_with_credential_key(self):
433-
"""Test that from_config creates header provider from credential_key."""
434-
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
435-
from google.adk.tools.tool_configs import ToolArgsConfig
436-
437-
config = ToolArgsConfig(
438-
stdio_server_params={"command": "test_command", "args": []},
439-
credential_key="my_token",
440-
)
441-
442-
toolset = McpToolset.from_config(config, "/fake/path")
443-
444-
assert toolset._header_provider is not None
445-
446-
mock_context = Mock(spec=ReadonlyContext)
447-
mock_context.state = {"my_token": "test-jwt-123"}
448-
449-
headers = toolset._header_provider(mock_context)
450-
451-
assert headers == {"Authorization": "Bearer test-jwt-123"}
452-
453-
def test_from_config_credential_key_with_state_header_mapping(self):
454-
"""Test that credential_key and state_header_mapping combine."""
455-
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
456-
from google.adk.tools.tool_configs import ToolArgsConfig
457-
458-
config = ToolArgsConfig(
459-
stdio_server_params={"command": "test_command", "args": []},
460-
credential_key="jwt_token",
461-
state_header_mapping={"tenant_id": "X-Tenant-ID"},
462-
)
463-
464-
toolset = McpToolset.from_config(config, "/fake/path")
465-
466-
mock_context = Mock(spec=ReadonlyContext)
467-
mock_context.state = {
468-
"jwt_token": "my-jwt",
469-
"tenant_id": "tenant-42",
470-
}
471-
472-
headers = toolset._header_provider(mock_context)
473-
474-
assert headers == {
475-
"Authorization": "Bearer my-jwt",
476-
"X-Tenant-ID": "tenant-42",
477-
}
478-
479432
def test_from_config_with_strict_mode(self):
480433
"""Test that from_config respects state_header_strict setting."""
481434
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
@@ -500,77 +453,6 @@ def test_from_config_with_strict_mode(self):
500453
assert "dict" in str(exc_info.value)
501454

502455

503-
class TestCredentialKey:
504-
"""Test suite for credential_key on McpToolset.__init__."""
505-
506-
def test_credential_key_creates_bearer_header(self):
507-
"""Test credential_key reads token from state and sends as Bearer."""
508-
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
509-
510-
toolset = McpToolset(
511-
connection_params=StdioServerParameters(command="echo", args=[]),
512-
credential_key="auth_token",
513-
)
514-
515-
assert toolset._header_provider is not None
516-
517-
mock_context = Mock(spec=ReadonlyContext)
518-
mock_context.state = {"auth_token": "my-jwt-token"}
519-
520-
headers = toolset._header_provider(mock_context)
521-
522-
assert headers == {"Authorization": "Bearer my-jwt-token"}
523-
524-
def test_credential_key_missing_state_returns_empty(self):
525-
"""Test credential_key returns empty headers when key not in state."""
526-
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
527-
528-
toolset = McpToolset(
529-
connection_params=StdioServerParameters(command="echo", args=[]),
530-
credential_key="auth_token",
531-
)
532-
533-
mock_context = Mock(spec=ReadonlyContext)
534-
mock_context.state = {}
535-
536-
headers = toolset._header_provider(mock_context)
537-
538-
assert headers == {}
539-
540-
def test_credential_key_none_means_no_provider(self):
541-
"""Test that credential_key=None does not create a provider."""
542-
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
543-
544-
toolset = McpToolset(
545-
connection_params=StdioServerParameters(command="echo", args=[]),
546-
credential_key=None,
547-
)
548-
549-
assert toolset._header_provider is None
550-
551-
def test_credential_key_combines_with_header_provider(self):
552-
"""Test that credential_key and header_provider are combined."""
553-
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
554-
555-
custom_provider = lambda ctx: {"X-Custom": "value"}
556-
557-
toolset = McpToolset(
558-
connection_params=StdioServerParameters(command="echo", args=[]),
559-
credential_key="auth_token",
560-
header_provider=custom_provider,
561-
)
562-
563-
mock_context = Mock(spec=ReadonlyContext)
564-
mock_context.state = {"auth_token": "my-jwt"}
565-
566-
headers = toolset._header_provider(mock_context)
567-
568-
assert headers == {
569-
"Authorization": "Bearer my-jwt",
570-
"X-Custom": "value",
571-
}
572-
573-
574456
class TestRFC7230Compliance:
575457
"""Test suite for RFC 7230 compliant header handling."""
576458

0 commit comments

Comments
 (0)