-
Notifications
You must be signed in to change notification settings - Fork 20
Google ADK Sample with Tooling #70
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
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
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,22 @@ | ||
| GOOGLE_GENAI_USE_VERTEXAI=FALSE | ||
| GOOGLE_API_KEY= | ||
|
|
||
| # Agent365 Agentic Authentication Configuration | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID= | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET= | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID= | ||
| CONNECTIONS__SERVICE_CONNECTION__SETTINGS__SCOPES=https://api.botframework.com/.default | ||
|
|
||
| AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__AGENTIC__SETTINGS__TYPE=AgenticUserAuthorization | ||
| AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__AGENTIC__SETTINGS__SCOPES=https://graph.microsoft.com/.default | ||
| AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__AGENTIC__SETTINGS__ALTERNATEBLUEPRINTCONNECTIONNAME=https://graph.microsoft.com/.default | ||
|
|
||
| CONNECTIONSMAP__0__SERVICEURL=* | ||
| CONNECTIONSMAP__0__CONNECTION=SERVICE_CONNECTION | ||
|
|
||
| # These values are expected to be in the activity's recipient field | ||
| AGENTIC_UPN= | ||
| AGENTIC_NAME= | ||
| AGENTIC_USER_ID= | ||
| AGENTIC_APP_ID= | ||
| AGENTIC_TENANT_ID= |
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,8 @@ | ||
| { | ||
| "mcpServers": [ | ||
| { | ||
| "mcpServerName": "mcp_MailTools", | ||
| "mcpServerUniqueName": "mcp_MailTools" | ||
| } | ||
| ] | ||
| } |
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,123 @@ | ||
| # Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| import asyncio | ||
| import os | ||
| from google.adk.agents import Agent | ||
| from dotenv import load_dotenv | ||
|
|
||
| # Load environment variables from .env file | ||
| load_dotenv() | ||
|
|
||
| from mcp_tool_registration_service import McpToolRegistrationService | ||
|
|
||
| from microsoft_agents_a365.observability.core.config import configure | ||
| from microsoft_agents_a365.observability.core.middleware.baggage_builder import ( | ||
| BaggageBuilder, | ||
| ) | ||
|
|
||
| from google.adk.runners import Runner | ||
| from google.adk.sessions.in_memory_session_service import InMemorySessionService | ||
|
|
||
| from microsoft_agents.activity import load_configuration_from_env, Activity, ChannelAccount, ActivityTypes | ||
| from microsoft_agents.hosting.core import Authorization, MemoryStorage, TurnContext, ClaimsIdentity, AuthenticationConstants | ||
| from microsoft_agents.hosting.aiohttp import CloudAdapter | ||
| from microsoft_agents.authentication.msal import MsalConnectionManager | ||
|
|
||
| agents_sdk_config = load_configuration_from_env(os.environ) | ||
|
|
||
| async def main(): | ||
| # Google ADK expects root_agent to be defined at module level | ||
| # Create the base agent synchronously | ||
| my_agent = Agent( | ||
| name="my_agent", | ||
| model="gemini-2.0-flash", | ||
| description=( | ||
| "Agent to test Mcp tools." | ||
| ), | ||
| instruction=( | ||
| "You are a helpful agent who can use tools. If you encounter any errors, please provide the exact error message you encounter." | ||
| ), | ||
| ) | ||
|
|
||
| auth = Authorization( | ||
| storage=MemoryStorage(), | ||
| connection_manager=MsalConnectionManager(**agents_sdk_config), | ||
| **agents_sdk_config | ||
| ) | ||
|
|
||
| turnContext = TurnContext( | ||
| adapter_or_context=CloudAdapter(), | ||
| request=Activity( | ||
| type=ActivityTypes.message, | ||
| text="", | ||
| from_property=ChannelAccount( | ||
| id='user1', | ||
| name='User One' | ||
| ), | ||
| recipient=ChannelAccount( | ||
| id=os.getenv("AGENTIC_UPN", ""), | ||
| name=os.getenv("AGENTIC_NAME", ""), | ||
| agentic_user_id=os.getenv("AGENTIC_USER_ID", ""), | ||
| agentic_app_id=os.getenv("AGENTIC_APP_ID", ""), | ||
| tenant_id=os.getenv("AGENTIC_TENANT_ID", ""), | ||
| role="agenticUser" | ||
| ) | ||
| ), | ||
| identity=ClaimsIdentity( | ||
| { | ||
| AuthenticationConstants.AUDIENCE_CLAIM: "anonymous", | ||
| AuthenticationConstants.APP_ID_CLAIM: "anonymous-app", | ||
| }, | ||
| False, | ||
| "Anonymous", | ||
| ) | ||
| ) | ||
|
|
||
| if not (await auth._start_or_continue_sign_in(turnContext, None, 'AGENTIC')).sign_in_complete(): | ||
| print("Sign-in required. Exiting.") | ||
| return | ||
|
|
||
| tool_service = McpToolRegistrationService() | ||
|
|
||
| my_agent = await tool_service.add_tool_servers_to_agent( | ||
| agent=my_agent, | ||
| agentic_app_id=os.getenv("AGENTIC_APP_ID", "agent123"), | ||
| auth=auth, | ||
| context=turnContext, | ||
| auth_token=os.getenv("BEARER_TOKEN", ""), | ||
| ) | ||
|
|
||
| # Create runner | ||
| runner = Runner( | ||
| app_name="agents", | ||
| agent=my_agent, | ||
| session_service=InMemorySessionService(), | ||
| ) | ||
|
|
||
| # Run agent | ||
| try: | ||
| user_message = input("Enter your message to the agent: ") | ||
| with BaggageBuilder().tenant_id("your-tenant-id").agent_id("agent123").build(): | ||
| _ = await runner.run_debug( | ||
| user_messages=[user_message] | ||
| ) | ||
| finally: | ||
| agent_tools = my_agent.tools | ||
| for tool in agent_tools: | ||
| if hasattr(tool, "close"): | ||
| await tool.close() | ||
|
|
||
| if __name__ == "__main__": | ||
| configure( | ||
| service_name="GoogleADKSampleAgent", | ||
| service_namespace="GoogleADKTesting", | ||
| ) | ||
|
|
||
| try: | ||
| asyncio.run(main()) | ||
| except KeyboardInterrupt: | ||
| print("\nShutting down gracefully...") | ||
| except Exception as e: | ||
| # Ignore cleanup errors during shutdown | ||
| if "cancel scope" not in str(e) and "RuntimeError" not in type(e).__name__: | ||
| raise | ||
92 changes: 92 additions & 0 deletions
92
python/google-adk/sample-agent/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,92 @@ | ||
| # Copyright (c) Microsoft. All rights reserved. | ||
|
|
||
| from typing import Optional | ||
| import logging | ||
|
|
||
| from google.adk.agents import Agent | ||
| from google.adk.tools.mcp_tool.mcp_toolset import McpToolset, StreamableHTTPConnectionParams | ||
|
|
||
| from microsoft_agents.hosting.core import Authorization, TurnContext | ||
|
|
||
| from microsoft_agents_a365.tooling.services.mcp_tool_server_configuration_service import ( | ||
| McpToolServerConfigurationService, | ||
| ) | ||
|
|
||
| from microsoft_agents_a365.tooling.utils.utility import ( | ||
| get_mcp_platform_authentication_scope, | ||
| ) | ||
|
|
||
| class McpToolRegistrationService: | ||
| """Service for managing MCP tools and servers for an agent""" | ||
|
|
||
| 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) | ||
|
|
||
| async def add_tool_servers_to_agent( | ||
| self, | ||
| agent: Agent, | ||
| agentic_app_id: str, | ||
| auth: Authorization, | ||
| context: TurnContext, | ||
| auth_token: Optional[str] = None, | ||
| ): | ||
| """ | ||
| Add new MCP servers to the agent by creating a new Agent instance. | ||
|
|
||
| Note: This method creates a new Agent instance with MCP servers configured. | ||
|
|
||
| Args: | ||
| agent: The existing agent to add servers to. | ||
| agentic_app_id: Agentic App ID for the agent. | ||
| auth: Authorization object used to exchange tokens for MCP server access. | ||
| 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: | ||
| New Agent instance with all MCP servers | ||
| """ | ||
|
|
||
| if not auth_token: | ||
| scopes = get_mcp_platform_authentication_scope() | ||
| auth_token_obj = await auth.exchange_token(context, scopes, "AGENTIC") | ||
| auth_token = auth_token_obj.token | ||
|
|
||
| self._logger.info(f"Listing MCP tool servers for agent {agentic_app_id}") | ||
| mcp_server_configs = await self.config_service.list_tool_servers( | ||
| agentic_app_id=agentic_app_id, | ||
| auth_token=auth_token | ||
| ) | ||
|
|
||
| self._logger.info(f"Loaded {len(mcp_server_configs)} MCP server configurations") | ||
|
|
||
| # Convert MCP server configs to MCPServerInfo objects | ||
| mcp_servers_info = [] | ||
| mcp_server_headers = { | ||
| "Authorization": f"Bearer {auth_token}" | ||
| } | ||
|
|
||
| for server_config in mcp_server_configs: | ||
| server_info = McpToolset( | ||
| connection_params=StreamableHTTPConnectionParams( | ||
| url=server_config.mcp_server_unique_name, | ||
| headers=mcp_server_headers | ||
| ) | ||
| ) | ||
|
|
||
| mcp_servers_info.append(server_info) | ||
|
|
||
| all_tools = agent.tools + mcp_servers_info | ||
|
|
||
| return Agent( | ||
| name=agent.name, | ||
| model=agent.model, | ||
| description=agent.description, | ||
| tools=all_tools, | ||
| ) |
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,66 @@ | ||
| [project] | ||
| name = "sample-google-adk" | ||
| version = "0.1.0" | ||
| description = "Sample Google ADK Agent using Microsoft Agent 365 SDK" | ||
| authors = [ | ||
| { name = "Microsoft", email = "support@microsoft.com" } | ||
| ] | ||
| dependencies = [ | ||
| # Google ADK -- official package | ||
| "google-adk", | ||
JesuTerraz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Microsoft Agents SDK - Official packages for hosting and integration | ||
| "microsoft-agents-hosting-aiohttp", | ||
| "microsoft-agents-hosting-core", | ||
| "microsoft-agents-authentication-msal", | ||
| "microsoft-agents-activity", | ||
|
|
||
| # Core dependencies | ||
| "python-dotenv", | ||
| "aiohttp", | ||
|
|
||
| # HTTP server support for MCP servers | ||
| "uvicorn[standard]>=0.20.0", | ||
| "fastapi>=0.100.0", | ||
|
|
||
| # HTTP client | ||
| "httpx>=0.24.0", | ||
|
|
||
| # Data validation | ||
| "pydantic>=2.0.0", | ||
|
|
||
| # Additional utilities | ||
| "typing-extensions>=4.0.0", | ||
|
|
||
| # Microsoft Agent 365 SDK packages | ||
| "microsoft_agents_a365_tooling >= 0.1.0", | ||
| "microsoft_agents_a365_observability_core >= 0.1.0", | ||
| ] | ||
| requires-python = ">=3.11" | ||
|
|
||
| # Package index configuration | ||
| # PyPI is the default/primary source | ||
| [[tool.uv.index]] | ||
| name = "pypi" | ||
| url = "https://pypi.org/simple" | ||
| default = true | ||
|
|
||
| [project.optional-dependencies] | ||
| dev = [ | ||
| # For development and testing | ||
| "pytest>=7.0.0", | ||
| "pytest-asyncio>=0.21.0", | ||
| ] | ||
|
|
||
| [build-system] | ||
| requires = ["setuptools>=61.0", "wheel"] | ||
| build-backend = "setuptools.build_meta" | ||
|
|
||
| [tool.setuptools] | ||
| # Don't include any Python modules in the package since this is a sample/script collection | ||
| py-modules = [] | ||
|
|
||
| [tool.setuptools.packages.find] | ||
| where = ["."] | ||
| include = ["*"] | ||
| exclude = ["build*", "dist*", "venv*"] | ||
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.