Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
26065ab
initial commit
Jan 24, 2026
1e191b4
update pyproject.toml
Jan 24, 2026
76050f5
test additions
Feb 3, 2026
a1f75ea
Merge branch 'main' into users/jterrazas/google-adk-support
Feb 3, 2026
e33a550
remove non-central versioning
Feb 3, 2026
ab3e5d5
format
Feb 3, 2026
b52eb06
format x2
Feb 3, 2026
9c8264e
ignore E402
Feb 3, 2026
80a96cb
remove duplicate folder
Feb 3, 2026
a9ecaeb
remove extra newline
Feb 3, 2026
5b58669
Fix Google ADK extension documentation and linting config (#157)
Copilot Feb 3, 2026
8aa1200
Align Google ADK extension with tooling extension conventions (#158)
Copilot Feb 3, 2026
124726c
Modify agent instead of creating a new instance
Feb 4, 2026
bdf4ba6
Merge branch 'users/jterrazas/google-adk-support' of https://github.c…
Feb 4, 2026
50387b6
Fix Google ADK extension documentation and log messages (#160)
Copilot Feb 4, 2026
b683bb6
Merge branch 'main' into users/jterrazas/google-adk-support
JesuTerraz Feb 5, 2026
c541109
Align Google ADK extension with repository conventions (#163)
Copilot Feb 5, 2026
35ccea0
format
Feb 5, 2026
4bbe9d4
Fix file structure path in design.md from google/ to googleadk/ (#166)
Copilot Feb 6, 2026
975e822
update to use url
Feb 6, 2026
391c7be
test fix
Feb 6, 2026
2a8b5c7
update uv.lock
Feb 6, 2026
ba4f87e
Merge branch 'main' into users/jterrazas/google-adk-support
Feb 6, 2026
e6ca941
fixing uv lock to pass tests
Feb 6, 2026
a3cbd62
Merge branch 'main' into users/jterrazas/google-adk-support
JesuTerraz Feb 6, 2026
76aa10b
Prevent duplicate MCP server registration in Google ADK tooling exten…
Copilot Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# microsoft-agents-a365-tooling-extensions-googleadk

[![PyPI](https://img.shields.io/pypi/v/microsoft-agents-a365-tooling-extensions-googleadk?label=PyPI&logo=pypi)](https://pypi.org/project/microsoft-agents-a365-tooling-extensions-googleadk)
[![PyPI Downloads](https://img.shields.io/pypi/dm/microsoft-agents-a365-tooling-extensions-googleadk?label=Downloads&logo=pypi)](https://pypi.org/project/microsoft-agents-a365-tooling-extensions-googleadk)

Google ADK (Agent Development Kit) specific tools and services for AI agent development. Provides MCP (Model Context Protocol) tool registration service for dynamically adding MCP servers to Google ADK-based agents.

## Installation

```bash
pip install microsoft-agents-a365-tooling-extensions-googleadk
```

## Usage

For usage examples and detailed documentation, see the [Tooling documentation](https://learn.microsoft.com/microsoft-agent-365/developer/tooling?tabs=python) on Microsoft Learn.

## Support

For issues, questions, or feedback:

- File issues in the [GitHub Issues](https://github.com/microsoft/Agent365-python/issues) section
- See the [main documentation](../../README.md) for more information

## Trademarks

*Microsoft, Windows, Microsoft Azure and/or other Microsoft products and services referenced in the documentation may be either trademarks or registered trademarks of Microsoft in the United States and/or other countries. The licenses for this project do not grant you rights to use any Microsoft names, logos, or trademarks. Microsoft's general trademark guidelines can be found at http://go.microsoft.com/fwlink/?LinkID=254653.*

## License

Copyright (c) Microsoft Corporation. All rights reserved.

Licensed under the MIT License - see the [LICENSE](../../LICENSE.md) file for details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Tooling Extensions - Google ADK - Design Document

This document describes the architecture and design of the `microsoft-agents-a365-tooling-extensions-googleadk` package.

## Overview

This extension adapts MCP tool server configurations to Google's Agent Development Kit (ADK), enabling Google ADK-based agents to use MCP tools through the `McpToolset` interface.

## Key Components

### McpToolRegistrationService

The main service for registering MCP tools with Google ADK agents.

```python
from microsoft_agents_a365.tooling.extensions.googleadk import McpToolRegistrationService

service = McpToolRegistrationService()

# Add MCP tools to existing agent (modified in place)
await service.add_tool_servers_to_agent(
agent=existing_agent,
auth=auth_context,
auth_handler_name="graph",
context=turn_context,
)
```

### Integration Flow

```
McpToolServerConfigurationService
List MCPServerConfig objects
McpToolRegistrationService.add_tool_servers_to_agent()
├── Exchange token for MCP scope
├── Create McpToolset for each server
└── Modify agent in place to add all tools
Google ADK Agent with MCP tools
```

### add_tool_servers_to_agent Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `agent` | `Agent` | The existing Google ADK agent |
| `auth` | `Authorization` | Auth context for token exchange |
| `auth_handler_name` | `str` | Name of auth handler |
| `context` | `TurnContext` | Conversation context |
| `auth_token` | `str \| None` | Optional pre-obtained token |

### McpToolset Creation

For each MCP server configuration:

```python
server_info = McpToolset(
connection_params=StreamableHTTPConnectionParams(
url=config.url,
headers={
"Authorization": f"Bearer {token}"
}
)
)
```

## File Structure

```
microsoft_agents_a365/tooling/extensions/googleadk/
├── __init__.py
└── services/
├── __init__.py
└── mcp_tool_registration_service.py
```

## Dependencies

- `google-adk` - Google Agent Development Kit
- `microsoft-agents-a365-tooling` - Core tooling service
- `microsoft-agents-hosting-core` - Authorization and TurnContext
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

"""
Google ADK extensions for Microsoft Agent 365 Tooling SDK
Google ADK (Agent Development Kit) specific tools and services for AI agent development.
Provides MCP (Model Context Protocol) tool registration service for dynamically
adding MCP servers to Google ADK-based agents.
Main Service:
- McpToolRegistrationService: Add MCP tool servers to Google ADK agents
This module includes implementations for:
- Google ADK agent creation with MCP (Model Context Protocol) server support
- MCP tool registration service for dynamically adding MCP servers to agents
- Authentication and authorization patterns for MCP server discovery
"""

__version__ = "1.0.0"

# Import services from the services module
from .services import McpToolRegistrationService

__all__ = [
"McpToolRegistrationService",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

"""
Services module for Google ADK tooling.
This package contains service implementations for MCP tool registration
and management within the Google ADK framework.
"""

from .mcp_tool_registration_service import McpToolRegistrationService

__all__ = [
"McpToolRegistrationService",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

"""
MCP Tool Registration Service for Google ADK.

This service provides MCP (Model Context Protocol) tool registration
capabilities for Google ADK-based agents.
"""

# Standard library imports
import logging
from typing import List, Optional

# Third-party imports
from google.adk.agents import Agent
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset, StreamableHTTPConnectionParams

# Local imports
from microsoft_agents.hosting.core import Authorization, TurnContext
from microsoft_agents_a365.runtime.utility import Utility
from microsoft_agents_a365.tooling.models import ToolOptions
from microsoft_agents_a365.tooling.services.mcp_tool_server_configuration_service import (
McpToolServerConfigurationService,
)
from microsoft_agents_a365.tooling.utils.constants import Constants
from microsoft_agents_a365.tooling.utils.utility import (
get_mcp_platform_authentication_scope,
)


class McpToolRegistrationService:
"""
Provides MCP tool registration services for Google ADK agents.

This service handles registration and management of MCP (Model Context Protocol)
tool servers with Google ADK agents.
"""

_orchestrator_name: str = "GoogleADK"

def __init__(self, logger: Optional[logging.Logger] = None):
"""
Initialize the MCP Tool Registration Service for Google ADK.

Args:
logger: Logger instance for logging operations.
"""
self._logger = logger or logging.getLogger(self.__class__.__name__)
self.config_service = McpToolServerConfigurationService(logger=self._logger)
self._connected_servers: List[McpToolset] = []

async def add_tool_servers_to_agent(
self,
agent: Agent,
auth: Authorization,
auth_handler_name: str,
context: TurnContext,
auth_token: Optional[str] = None,
) -> None:
"""
Add new MCP servers to the agent from MCP Platform.

Note: Modifies the provided agent in place to add new MCP tool servers.

Args:
agent: The existing agent to add servers to.
auth: Authorization object used to exchange tokens for MCP server access.
auth_handler_name: Name of the authorization handler.
context: TurnContext object representing the current turn/session context.
auth_token: Authentication token to access the MCP servers.
If not provided, will be obtained using `auth` and `context`.

Returns:
None
"""
if not auth_token:
scopes = get_mcp_platform_authentication_scope()
auth_token_obj = await auth.exchange_token(context, scopes, auth_handler_name)
auth_token = auth_token_obj.token

agentic_app_id = Utility.resolve_agent_identity(context, auth_token)
self._logger.info(f"Listing MCP tool servers for agent {agentic_app_id}")

options = ToolOptions(orchestrator_name=self._orchestrator_name)
mcp_server_configs = await self.config_service.list_tool_servers(
agentic_app_id=agentic_app_id,
auth_token=auth_token,
options=options,
)

self._logger.info(f"Loaded {len(mcp_server_configs)} MCP server configurations")

# Collect existing server URLs to prevent duplicates (use set for O(1) lookup)
existing_server_urls = set()
for tool in agent.tools:
# Check if the tool is an McpToolset and has a connection_params.url
if hasattr(tool, "connection_params") and hasattr(tool.connection_params, "url"):
existing_server_urls.add(tool.connection_params.url)

self._logger.debug(f"Found {len(existing_server_urls)} existing MCP servers in agent")

# Convert MCP server configs to McpToolset objects (only new ones)
mcp_servers_info = []
mcp_server_headers = {
Constants.Headers.AUTHORIZATION: f"{Constants.Headers.BEARER_PREFIX} {auth_token}",
Constants.Headers.USER_AGENT: Utility.get_user_agent_header(self._orchestrator_name),
}

for server_config in mcp_server_configs:
# Skip if server URL already exists
if server_config.url in existing_server_urls:
self._logger.debug(
f"Skipping MCP server '{server_config.mcp_server_name}' "
f"at {server_config.url} - already exists in agent"
)
continue

try:
server_info = McpToolset(
connection_params=StreamableHTTPConnectionParams(
url=server_config.url,
headers=mcp_server_headers,
)
)

mcp_servers_info.append(server_info)
self._connected_servers.append(server_info)
existing_server_urls.add(server_config.url)
self._logger.info(
f"Created MCP toolset for '{server_config.mcp_server_name}' "
f"at {server_config.url}"
)

except Exception as tool_ex:
server_name = getattr(server_config, "mcp_server_name", "Unknown")
self._logger.warning(f"Failed to create MCP toolset for {server_name}: {tool_ex}")
continue

# Only modify agent.tools if we have new servers to add
if mcp_servers_info:
all_tools = list(agent.tools) + mcp_servers_info
agent.tools = all_tools
self._logger.info(
f"Successfully configured agent with {len(mcp_servers_info)} new MCP tool servers "
f"(total tools: {len(all_tools)})"
)
else:
self._logger.info("No new MCP servers to add to agent")

async def cleanup(self):
"""Clean up any resources used by the service."""
try:
for toolset in self._connected_servers:
try:
if hasattr(toolset, "close"):
await toolset.close()
except Exception as cleanup_ex:
self._logger.debug(f"Error during cleanup: {cleanup_ex}")
self._connected_servers.clear()
except Exception as ex:
self._logger.debug(f"Error during service cleanup: {ex}")
Loading