> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Google ADK

> Connect StackOne MCP to Google ADK for building sophisticated AI agents with Gemini models and native MCP support.

## Overview

Google's Agent Development Kit (ADK) is an open-source, code-first Python toolkit for building, evaluating, and deploying AI agents. ADK includes native MCP support via the `McpToolset` class, enabling direct integration with StackOne's MCP server.

[Official Documentation](https://google.github.io/adk-docs/)

## Installation

```bash theme={null}
pip install google-adk
```

Or with uv:

```bash theme={null}
uv add google-adk
```

## Quick Start

Connect to StackOne MCP and create an ADK agent using the Runner pattern:

```python theme={null}
import os
import base64
import asyncio
from google.adk import Runner
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams
from google.adk.sessions import InMemorySessionService
from google.genai import types

# Configuration - API keys from environment (secrets)
STACKONE_API_KEY = os.getenv("STACKONE_API_KEY")
os.environ["GOOGLE_API_KEY"] = os.getenv("GOOGLE_API_KEY")

# Encode API key for Basic auth
auth_token = base64.b64encode(f"{STACKONE_API_KEY}:".encode()).decode()

def create_stackone_agent(account_id: str) -> LlmAgent:
    """
    Create an agent for a specific StackOne account.

    In production, account_id should come from:
    - User/tenant context
    - Database lookup based on authenticated user
    - Request parameters
    """
    return LlmAgent(
        model="gemini-2.5-pro",
        name="stackone_assistant",
        instruction="You are a helpful assistant with access to data from connected platforms via StackOne.",
        tools=[
            McpToolset(
                connection_params=StreamableHTTPConnectionParams(
                    url="https://api.stackone.com/mcp",
                    headers={
                        "Authorization": f"Basic {auth_token}",
                        "x-account-id": account_id
                    }
                ),
                tool_name_prefix="stackone_"
            )
        ],
    )

async def main():
    # Get account_id from user context (not environment variable)
    account_id = get_user_account_id()  # Your function to determine this

    # Create agent for this specific account
    agent = create_stackone_agent(account_id)

    # Create runner with in-memory session service
    runner = Runner(
        agent=agent,
        app_name="stackone_demo",
        session_service=InMemorySessionService()
    )

    # Create a session
    await runner.session_service.create_session(
        app_name="stackone_demo",
        user_id="user_1",
        session_id="session_1"
    )

    # Create and send a message
    message = types.Content(parts=[types.Part(text="List workers from Workday, limit 5")], role="user")

    # Run the agent and collect response
    async for event in runner.run_async(
        user_id="user_1",
        session_id="session_1",
        new_message=message
    ):
        if hasattr(event, 'content') and event.content:
            if hasattr(event.content, 'parts'):
                for part in event.content.parts:
                    if hasattr(part, 'text') and part.text:
                        print(part.text)

asyncio.run(main())
```

## Environment Variables

```bash theme={null}
export STACKONE_API_KEY="your_stackone_api_key"
export GOOGLE_API_KEY="your_google_api_key"
```

<Note>
  **Account ID**: The StackOne account ID should be determined from user context (e.g., which tenant/customer is using the agent), not from environment variables. Pass it as a parameter when creating the agent.
</Note>

## Multi-Turn Conversations

Continue conversations by reusing the same session:

```python theme={null}
# First query
message1 = types.Content(parts=[types.Part(text="List 3 workers")], role="user")
async for event in runner.run_async(user_id="user_1", session_id="session_1", new_message=message1):
    # Process first response...
    pass

# Follow-up query (uses same session for context)
message2 = types.Content(parts=[types.Part(text="Show me details for the first worker")], role="user")
async for event in runner.run_async(user_id="user_1", session_id="session_1", new_message=message2):
    # Process follow-up response...
    pass
```

## Tool Filtering

Restrict which StackOne tools are exposed to the agent for security:

```python theme={null}
McpToolset(
    connection_params=StreamableHTTPConnectionParams(
        url="https://api.stackone.com/mcp",
        headers={
            "Authorization": f"Basic {auth_token}",
            "x-account-id": account_id
        }
    ),
    tool_filter=[
        "workday_list_workers",
        "workday_get_worker",
        "salesforce_crm_list_accounts"
    ]  # Only expose specific tools
)
```

<Note>
  **Required Headers**: Only `Authorization` and `x-account-id` are required. Additional headers like `Content-Type`, `Accept`, and `MCP-Protocol-Version` are handled automatically by the ADK client.
</Note>

<Note>
  **Class Name Update**: In ADK v1.17.0+, use `McpToolset` (not `MCPToolset`). The old capitalization is deprecated but still works with a warning.
</Note>

## Resources

* [ADK Documentation](https://google.github.io/adk-docs/)
* [MCP Tools Guide](https://google.github.io/adk-docs/tools/mcp-tools/)
* [ADK Authentication](https://google.github.io/adk-docs/tools/authentication/)
* [Gemini API](https://ai.google.dev/gemini-api/docs)
* [StackOne Authentication](/mcp/auth-security)

## Next Steps

<CardGroup cols={2}>
  <Card title="Pydantic AI" icon="robot" href="/mcp/framework-guides/pydantic-ai">
    Try Pydantic AI for Python agents
  </Card>

  <Card title="Vercel AI SDK" icon="code" href="/mcp/framework-guides/vercel-ai-sdk">
    Build TypeScript agents with Vercel AI
  </Card>
</CardGroup>
