-
Notifications
You must be signed in to change notification settings - Fork 9
New Google ADK Tooling Extension #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
JesuTerraz
wants to merge
26
commits into
main
Choose a base branch
from
users/jterrazas/google-adk-support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
26065ab
initial commit
1e191b4
update pyproject.toml
76050f5
test additions
a1f75ea
Merge branch 'main' into users/jterrazas/google-adk-support
e33a550
remove non-central versioning
ab3e5d5
format
b52eb06
format x2
9c8264e
ignore E402
80a96cb
remove duplicate folder
a9ecaeb
remove extra newline
5b58669
Fix Google ADK extension documentation and linting config (#157)
Copilot 8aa1200
Align Google ADK extension with tooling extension conventions (#158)
Copilot 124726c
Modify agent instead of creating a new instance
bdf4ba6
Merge branch 'users/jterrazas/google-adk-support' of https://github.c…
50387b6
Fix Google ADK extension documentation and log messages (#160)
Copilot b683bb6
Merge branch 'main' into users/jterrazas/google-adk-support
JesuTerraz c541109
Align Google ADK extension with repository conventions (#163)
Copilot 35ccea0
format
4bbe9d4
Fix file structure path in design.md from google/ to googleadk/ (#166)
Copilot 975e822
update to use url
391c7be
test fix
2a8b5c7
update uv.lock
ba4f87e
Merge branch 'main' into users/jterrazas/google-adk-support
e6ca941
fixing uv lock to pass tests
a3cbd62
Merge branch 'main' into users/jterrazas/google-adk-support
JesuTerraz 76aa10b
Prevent duplicate MCP server registration in Google ADK tooling exten…
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
libraries/microsoft-agents-a365-tooling-extensions-googleadk/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # microsoft-agents-a365-tooling-extensions-googleadk | ||
|
|
||
| [](https://pypi.org/project/microsoft-agents-a365-tooling-extensions-googleadk) | ||
| [](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. |
87 changes: 87 additions & 0 deletions
87
libraries/microsoft-agents-a365-tooling-extensions-googleadk/docs/design.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | ||
27 changes: 27 additions & 0 deletions
27
...oling-extensions-googleadk/microsoft_agents_a365/tooling/extensions/googleadk/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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", | ||
| ] |
15 changes: 15 additions & 0 deletions
15
...ensions-googleadk/microsoft_agents_a365/tooling/extensions/googleadk/services/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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", | ||
| ] |
162 changes: 162 additions & 0 deletions
162
...rosoft_agents_a365/tooling/extensions/googleadk/services/mcp_tool_registration_service.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. | ||
pontemonti marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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, | ||
| ) | ||
JesuTerraz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) | ||
|
|
||
| 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}" | ||
| ) | ||
JesuTerraz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| 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}") | ||
JesuTerraz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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}") | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.