Overview

All components at a glance

Client
Gradio
Chat UI
Destination, dates, budget, home currency form · streaming step tracker · MCP trace tab showing raw tool call/result JSON
Gradio 6.10Hugging Face Spaces
crew.kickoff() run in a background thread, polled every 0.35s
Agents
calls MCP
1
Flight + Forex Specialist
collect_cost_context_task
calls MCP
2
Budget Profiler
profile_budget_task
3
Fin-Ops Planner
build_itinerary_task — no tool calls
CrewAI Process.sequential. LLM: OpenRouter openai/gpt-4.1-mini via CrewAI's LLM class.
stdio subprocess — MCPServerStdio, filtered to 3 named tools
My Contribution
MCP Tool Server — mcp/server.py (FastMCP)
search_flight_tool
SerpApi — Google Flights
IATA resolution · 2-call round-trip pattern via departure_token · retries on 429/5xx
get_exchange_rate_tool
Open Exchange Rates
USD-based free tier · triangulated cross-rates · 1hr in-memory cache
estimate_destination_costs_tool
Numbeo (scraped)
requests + BeautifulSoup · seasonality multiplier · 24hr cache
structured Pydantic outputs, validated by guardrail functions
Output
travel_plan.md
Final itinerary
Trip Summary · Day-by-Day Itinerary · Daily Spending Guidance · Final Budget Summary · Assumptions and Limitations
Request Lifecycle

One trip request — step by step with design rationale

User Action
Submit trip request
Destination, date range, total budget, home currency via Gradio form
Step 1 — Flight + Forex Specialist
Calls all three MCP tools
Flight pricing, exchange rate, destination cost estimate → CostContextOutput
Step 2 — Budget Profiler
Converts total budget to daily caps
May re-call MCP tools if upstream data is missing → BudgetProfileOutput
Step 3 — Fin-Ops Planner
Synthesizes the itinerary
Reasons only over the two structured upstream outputs — makes no tool calls of its own
Complete
travel_plan.md rendered in Gradio
Step tracker and MCP trace tab reflect every tool call made along the way
Context Example run: a 7-day Paris trip on a $4,000 budget, broken down day-by-day with a final accommodation/food/transport/entertainment table.
My contribution The three MCP tools this agent calls — search_flight_tool, get_exchange_rate_tool, estimate_destination_costs_tool — are what I built for the squad. Everyone else's part (agent logic, MCP integration into CrewAI, the Gradio UI, overall architecture) is credited to the rest of the team.
Round-trip flights Google Flights requires two separate calls for a round trip — the tool fetches outbound offers first, then uses the cheapest offer's departure_token to fetch matching returns.
Why re-call tools here? If the upstream flight/forex data came back thin, the Budget Profiler can call the same MCP tools again rather than working from incomplete numbers.
Sequential, not hierarchical An earlier hierarchical setup routed tasks through a manager step that didn't reliably invoke the MCP tools.
Direct sequential process Moving to Process.sequential made tool use consistent — the Planner only ever sees clean, structured data from the two upstream agents, never touching a tool itself.
Accuracy over completeness The Planner is explicitly instructed not to invent missing prices — thin API data shows up as visible caveats in "Assumptions and Limitations" rather than being silently smoothed over.
My MCP Tools

Real external data sources behind each tool

Flights
search_flight_tool
Calls SerpApi's Google Flights engine directly
Resolves city names to IATA codes via SerpApi's autocomplete
Retries on 429/5xx via urllib3 Retry
Free tier: 100 searches/month, mitigated with request discipline
Currency
get_exchange_rate_tool
Open Exchange Rates free tier — USD-based only
Non-USD pairs computed via USD triangulation
Fetches all ~170 rates in one call, caches 1 hour
Cost of Living
estimate_destination_costs_tool
Scrapes Numbeo (no API key) with requests + BeautifulSoup
City slug resolution with a slugify fallback
Monthly seasonality multiplier (0.90–1.15), cached 24 hours
Chosen over Numbeo's paid API specifically to avoid cost on a capstone project
Decisions

Every architectural decision — problem and rationale

DecisionWhat the naive approach gets wrongWhy this solution is better
MCP as a separate module Baking tool logic directly into agent code ties tool dependencies and runtime to the crew process MCP server kept decoupled so it could be reused by another client or deployed independently as a remote HTTP server later.
Sequential over hierarchical process Hierarchical mode routed tasks through a manager step that didn't reliably invoke MCP tools Direct sequential process made tool use consistent across every run.
USD triangulation for FX Calling the exchange-rate API once per currency pair burns through a 1,000-request/month free tier fast One call fetches all ~170 USD-based rates; any pair is computed locally and cached for an hour.
Scraping Numbeo instead of its paid API Numbeo's paid API costs real money for a capstone project with no revenue A targeted scrape of the public cost-of-living page avoids that cost, accepting the trade-off that the tool depends on Numbeo's HTML structure staying stable.
Threading lock around MCP calls CrewAI 1.10's parallel tool execution raced the stdio transport, corrupting concurrent tool calls A lock serializes MCP calls, patched at the integration layer rather than waiting on an upstream CrewAI fix.
Planner never invents missing data Silently filling gaps with plausible numbers looks complete but misleads the traveler on real spend Thin or missing API data is explicitly flagged as an assumption or limitation in the final output instead.
Fin-Ops Travel Planner — Andela AI Engineering Bootcamp Capstone (5-person squad) CrewAI · Model Context Protocol · Gradio · Hugging Face Spaces