diff --git a/src/google/adk/integrations/agent_registry/agent_registry.py b/src/google/adk/integrations/agent_registry/agent_registry.py index 2a9989f250..c5f907f0b5 100644 --- a/src/google/adk/integrations/agent_registry/agent_registry.py +++ b/src/google/adk/integrations/agent_registry/agent_registry.py @@ -457,6 +457,17 @@ def get_mcp_toolset( if not isinstance(mcp_server_id, str): mcp_server_id = None + # Prefer the App Hub resource-name URI (`RuntimeReference.uri`) for the + # destination span attribute, since that is the identifier form the + # Agent Platform Topology view's connection matcher resolves against. + # Fall back to `mcpServerId` if the attribute is absent. + runtime_reference = (server_details.get("attributes") or {}).get( + "agentregistry.googleapis.com/system/RuntimeReference" + ) or {} + destination_resource_id = runtime_reference.get("uri") + if not isinstance(destination_resource_id, str): + destination_resource_id = mcp_server_id + endpoint_uri, _, _ = self._get_connection_uri( server_details, protocol_binding=_compat.TP_JSONRPC ) @@ -491,7 +502,7 @@ def combined_header_provider(context: ReadonlyContext) -> Dict[str, str]: return headers return AgentRegistrySingleMcpToolset( - destination_resource_id=mcp_server_id, + destination_resource_id=destination_resource_id, connection_params=connection_params, tool_name_prefix=name, header_provider=combined_header_provider, diff --git a/tests/unittests/integrations/agent_registry/test_agent_registry.py b/tests/unittests/integrations/agent_registry/test_agent_registry.py index b178b1b8b7..84825fbce5 100644 --- a/tests/unittests/integrations/agent_registry/test_agent_registry.py +++ b/tests/unittests/integrations/agent_registry/test_agent_registry.py @@ -175,6 +175,71 @@ async def test_get_mcp_toolset_adds_destination_id( == "urn:mcp:googleapis.com:projects:1234:locations:global:bigquery" ) + @pytest.mark.asyncio + @patch( + "google.adk.tools.mcp_tool.mcp_session_manager.MCPSessionManager.create_session", + new_callable=AsyncMock, + ) + async def test_get_mcp_toolset_prefers_runtime_reference_uri( + self, mock_create_session, registry + ): + """destination ID should come from RuntimeReference.uri, not mcpServerId. + + App Hub / Agent Platform Topology matches on the RuntimeReference URI + form, not the mcpServerId urn form, so the two must not be conflated. + """ + # Arrange + mcp_server_name = "test-mcp-server" + mock_api_response = MagicMock() + mock_api_response.json.return_value = { + "displayName": "TestPrefix", + "mcpServerId": ( + "urn:mcp:googleapis.com:projects:1234:locations:global:bigquery" + ), + "attributes": { + "agentregistry.googleapis.com/system/RuntimeReference": { + "uri": ( + "//agentregistry.googleapis.com/projects/1234/locations/" + "global/services/bigquery" + ), + }, + }, + "interfaces": [{ + "url": "https://mcp.com", + "protocolBinding": "JSONRPC", + }], + } + registry._session.get.return_value = mock_api_response + + registry._credentials.token = "token" + registry._credentials.refresh = MagicMock() + + mock_session = AsyncMock(spec=ClientSession) + mock_create_session.return_value = mock_session + + mock_session.list_tools.return_value = ListToolsResult( + tools=[ + Tool( + name="tool1", + description="d1", + inputs={}, + outputs={}, + inputSchema={}, + ), + ] + ) + + # Act + toolset = registry.get_mcp_toolset(mcp_server_name) + tools = await toolset.get_tools() + + # Assert + assert len(tools) == 1 + assert tools[0].custom_metadata.get(GCP_MCP_SERVER_DESTINATION_ID) == ( + "//agentregistry.googleapis.com/projects/1234/locations/global/" + "services/bigquery" + ) + @pytest.mark.asyncio @patch( "google.adk.tools.mcp_tool.mcp_session_manager.MCPSessionManager.create_session",