MCP
The currency agent holds an MCP toolset pointed at Streamable HTTP on /mcp. It can list get_exchange_rate and call it. The tool's arguments and the Frankfurter payload are visible to that agent. The travel agent never sees them.
Russell Sakauye
Entrepreneur building with AI agents | PMP | Ex-Shopify PMO | Okotoks, AB
CIW workshop · 4 November 2026
One orchestrator plans the trip. Weather stays in the same process. Currency is asked of a second agent, which calls a tool for the rate. Built with Google's open-source Agent Development Kit for a personal workshop.
The travel agent does not fetch rates or weather itself. It hands each part to a specialist. Only the currency specialist leaves the process.
Labels name the protocol. Colour repeats the same four roles and is not the only cue.
They look similar from the orchestrator, because both specialists are wrapped as tools. Underneath, the contracts differ.
The currency agent holds an MCP toolset pointed at Streamable HTTP on /mcp. It can list get_exchange_rate and call it. The tool's arguments and the Frankfurter payload are visible to that agent. The travel agent never sees them.
The currency agent is served with to_a2a and publishes a card at /.well-known/agent-card.json. The travel agent sends a JSON-RPC message to that agent. Multi-turn state and the MCP tools stay inside the currency service.
This is the path that passed on 4 November 2026, written up for the workshop. The longer public codelab covers the same system in more sections. Outputs below are from that recorded run.
A fresh cloud project, billing on, and a budget alert (the notes use $10, with mail at 50%, 90%, and 100%) before any deploy. The verified run used under $0.05. The alert is what catches a service left up.
Pin 3.13. An unpinned sync can pick 3.15, which breaks beartype inside fastmcp. Copy .env.example: enterprise mode, your-project-id, location global. On a Mac, point the Cloud SDK at Homebrew Python if the system one is 3.9, and turn off the ADK telemetry prompt.
FastMCP on port 8080. Recorded call get_exchange_rate from USD to EUR returned amount 1.0, base USD, date 2026-11-04, EUR rate 0.88755.
Port 8081. The card listed skills currency_agent and currency_agent-get_exchange_rate. "how much is 100 USD in GBP?" came back as 100 USD = 74.08 GBP (rate 0.74075).
Port 8082. Weather is a local subagent. Currency is a remote A2A agent. Both are wrapped the same way. The London question and the recorded answer are in the replay.
Deploy the MCP server, then the currency agent. Read the public URL and set AGENT_URL so the card advertises https on port 443. Then deploy the travel agent with that URL. The demo flag --allow-unauthenticated makes each service public.
Remove currency-mcp-server, currency-agent, and travel-agent. The verified cleanup listed 0 items. Do this before you stop, even if a later deploy failed.
Asked
I'm planning a trip to London. What is the weather like and how much is 200 EUR in GBP?
10°C 50°F
Travel agent, in-process weather subagent, wttr.in
166.92 GBP
Travel agent, currency agent over A2A, currency MCP server, Frankfurter
Same day, the MCP probe USD to EUR returned {"amount":1.0,"base":"USD","date":"2026-11-04","rates":{"EUR":0.88755}}.
The currency agent, asked "how much is 100 USD in GBP?", answered 100 USD = 74.08 GBP (rate 0.74075).
List tools, call a tool, get a structured result. The currency server is a good first tool because the contract is small and the upstream API is public.
Discovery is the card. The caller does not import the callee's tools. That is why the currency agent can move to its own service without the travel agent changing shape.
The weather helper is the same kind of tool wrapper as the remote currency agent. Promote a helper to A2A when it crosses a service, a repo, or a language.
On Cloud Run, deploy first, read the service URL, then set AGENT_URL. A card that still says localhost cannot be called from the travel service.
From apps/ciw-adk-travel-agent. The README next to this site has Mac gotchas, the Cloud Run order, the AGENT_URL update, and the mandatory delete of all three public services. Nothing on this page is hosted.
uv sync --group dev
uv run python currency_mcp_server/server.py
uv run python currency_agent/agent.py
uv run python travel_agent/agent.py
Three terminals, in that order. Then open http://localhost:8082. Offline tests, with the network mocked, are uv run pytest.
Off by default. Turning this on does not call anything until you send. If port 8082 is quiet, the page says so and stays on the recorded answer.