TL;DR: Use the Agent Development Kit's McpToolset with StreamableHTTPConnectionParams to connect to Ballet's MCP endpoint, or define a FunctionTool that calls the execute endpoint. Point the toolset at https://api.ballet.dev/mcp with an Authorization header and add it to your agent's tools.
Python developers building agents with Google's Agent Development Kit (ADK).
Attach an McpToolset configured for remote Streamable HTTP. The toolset imports Ballet's tools and manages the connection lifecycle.
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import McpToolset, StreamableHTTPConnectionParams
import os
ballet_tools = McpToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://api.ballet.dev/mcp",
headers={"Authorization": f"Bearer {os.environ['BALLET_API_TOKEN']}"},
),
# optional: restrict which tools the agent can call
tool_filter=["list_playbooks", "run_playbook", "get_run"],
)
root_agent = LlmAgent(
model="gemini-2.5-flash",
name="ops_agent",
instruction="You run Ballet playbooks to complete operational tasks.",
tools=[ballet_tools],
)
Use McpToolset (lowercase "c"); the older MCPToolset spelling is deprecated. For per-request auth, pass a header_provider callable instead of static headers.
To expose a single playbook, wrap the REST execute endpoint in a function and register it as a tool.
import json, os, httpx
from google.adk.agents import LlmAgent
async def run_onboarding(customer_id: str) -> dict:
"""Run the customer onboarding playbook in Ballet."""
url = f"https://api.ballet.dev/api/playbooks/{os.environ['BALLET_PLAYBOOK_ID']}/execute"
headers = {
"Authorization": f"Bearer {os.environ['BALLET_API_TOKEN']}",
"Content-Type": "application/json",
}
run = None
async with httpx.AsyncClient(timeout=None) as http:
async with http.stream("POST", url, headers=headers,
json={"input": {"customerId": customer_id}}) as res:
async for line in res.aiter_lines():
if line.startswith("data:"):
event = json.loads(line[5:].strip())
if event.get("type") == "run_stop":
run = event["run"]
return {"success": run and run.get("success"), "output": run and run.get("output")}
root_agent = LlmAgent(
model="gemini-2.5-flash",
name="onboarding_agent",
instruction="Use run_onboarding to onboard new customers.",
tools=[run_onboarding],
)
ADK wraps a plain function as a tool automatically. See Run playbooks over the REST API for event details.
Both surfaces are served from api.ballet.dev. app.ballet.dev serves Ballet Studio and will not answer API or MCP requests.