Build a Hotel Search AI Agent with MCP

Learn the Model Context Protocol and build a hotel search agent that connects an Airbnb MCP server to a Gemini agent for live listings, weather, and web search.

Jun 19, 202614 min readFollow

Topics You Will Master

Understanding the Model Context Protocol architecture and primitives
Installing the Node.js and uv toolchain that MCP servers run on
Connecting an Airbnb MCP server with MultiServerMCPClient
Building a hotel-search agent with live weather and web search

The Model Context Protocol (MCP) is the universal standard for connecting AI models to systems, data, and tools. This lesson introduces MCP from first principles and then builds your first real project: a hotel-search agent that talks to an Airbnb MCP server using LangChain and Gemini.

We cover the MCP architecture, its primitives and transports, the connection lifecycle, and the toolchain MCP servers need. Then we wire an Airbnb server into an agent with MultiServerMCPClient so it returns live listings alongside weather and web search.

Note

This is the first project lesson. It assumes you are comfortable with create_agent, tools, and the shared scripts/base_tools.py. If not, review LangChain Agent Fundamentals first.

What Is the Model Context Protocol?

Previously, connecting an LLM to data required bespoke integration code for every single source — custom SQL code here, an ad-hoc API integration there, complex scripting for Git. The systems were isolated, fragile, and error-prone.

MCP fixes this the way USB-C fixed device connectors. Just as a USB-C port accepts a hard drive, camera, or monitor without custom wiring, MCP lets an AI plug into any data source through one standardized interface. One protocol, thousands of tools.

The Architecture of a Connection

An MCP connection has four parts, arranged in a line from the AI down to the real data:

  • MCP Host — the AI application (e.g., Claude Desktop, an IDE, or your LangChain app). The "brain."
  • MCP Client — the messenger that maintains a 1:1 connection to a server.
  • MCP Server — the worker that translates a data source into MCP format.
  • Data Source — the reality: Postgres, Gmail, local files, an API.

The client and server talk over the Model Context Protocol boundary using JSON-RPC, while the server speaks the data source's native API.

The Three Primitives

MCP servers empower an AI through three primitives:

  1. Tools — executable functions the AI can invoke to perform actions or side effects, e.g. search_emails() or execute_sql_query().
  2. Resources — passive data the AI can read and analyze, e.g. file contents, database schemas, logs.
  3. Prompts — reusable templates that structure model behavior, e.g. a bug-report template or system instructions.

Protocol Layers

MCP separates two concerns so the data logic stays consistent everywhere:

  • Transport layer — handles communication channels. Stdio is a direct local process (fast, ideal for local development). HTTP/SSE (Server-Sent Events) is for remote servers with auth support.
  • Data layer — handles logic and schema using the JSON-RPC 2.0 message format, covering lifecycle, errors, and the primitives above.

Tip

Start with the stdio transport for local development. It is faster and requires no authentication.

The Connection Lifecycle

A connection moves through three phases:

Phase I — Initialization (the handshake). The client sends an initialize message negotiating three things: the protocol version (must match), capabilities (what each side can do), and identity (who you are). The server responds and the connection is established.

JSON
{
  "protocolVersion": "2025-06-18",
  "capabilities": {
    "sampling": {},
    "tools": { "listChanged": true }
  },
  "clientInfo": { "name": "example-client", "version": "1.0" }
}

Phase II — Tool discovery. The host asks "what can I do?" and the server responds with a registry of capabilities. Each tool ships a description and a JSON input schema, which lets the LLM "learn" the tool instantly:

JSON
{
  "name": "weather_current",
  "description": "Returns current weather for a location.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "location": { "type": "string" },
      "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
    },
    "required": ["location"]
  }
}

Phase III — Execution (the loop). The host issues a tools/call request; the server executes it and returns content:

JSON
{
  "method": "tools/call",
  "params": {
    "name": "weather_current",
    "arguments": { "location": "San Francisco", "units": "imperial" }
  }
}

The server pushes real-time updates (such as notifications/tools/list_changed) so the host always acts on the latest reality — no polling required.

The Power of Multi-Server Architecture

The host acts as an orchestrator, maintaining simultaneous connections to local and remote servers. The AI can read a local file (Filesystem server over stdio), query a database (Postgres server over stdio), and email the results (Gmail server over HTTP) — all in a single session. Connecting prebuilt servers takes just a few lines of configuration through a MultiServerMCPClient.

Note

Explore the full specification at the official site: search "Model Context Protocol modelcontextprotocol.io" for the latest reference. MCP is bidirectional too — servers can request sampling (ask the host's LLM to generate content) and elicitation (ask the user for input or confirmation).

Installing the Toolchain

MCP servers are small programs distributed through npm (Node) and PyPI (Python). You need two package runners: Node.js/npm (provides npx) and uv (provides uvx).

Install Node.js and npm

Windows: download the Node.js LTS installer from nodejs.org (it includes npm), run it, then verify:

POWERSHELL
node --version
npm --version

On Linux/macOS: install with Homebrew (brew install node) or NodeSource, then verify with the same two commands.

Install uv

Windows (PowerShell):

POWERSHELL
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

On Linux/macOS:

BASH
curl -LsSf https://astral.sh/uv/install.sh | sh

Verify both runners are available:

POWERSHELL
uv --version
uvx --version

Tip

You can also install uv with pip: pip install uv. The uvx command runs a Python tool in a temporary environment, the same way npx runs a Node package.

The Airbnb MCP Server

The Airbnb MCP server is perfect for a first project: it needs no authentication and works immediately for public listing searches. It is launched on demand with npx, so you do not install anything ahead of time.

We define its launch configuration as a dictionary. The command/args tell the client how to spawn the server, and transport is stdio for local use:

PYTHON
airbnb_config = {
    "airbnb": {
        "command": "npx",
        "args": ["-y", "@openbnb/mcp-server-airbnb", "--ignore-robots-txt"],
        "transport": "stdio",
    }
}

Note

Search "openbnb mcp-server-airbnb GitHub" for the server's source and options. The --ignore-robots-txt flag is required for the server to fetch public listings.

Building the Hotel Search Agent

The agent combines the Airbnb MCP tools with the two reusable tools from this series — web_search and get_weather — so it can find a place to stay, then check the weather and local news around it.

Start with imports and the model. We also reconfigure stdout to UTF-8 so emoji and special characters print correctly on Windows consoles:

PYTHON
import sys
import os

root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(root_dir)

from dotenv import load_dotenv
load_dotenv()

from langchain_google_genai import ChatGoogleGenerativeAI
from langchain.agents import create_agent
from langchain.messages import HumanMessage
from langchain_mcp_adapters.client import MultiServerMCPClient
import asyncio

from scripts import base_tools, prompts

# Set UTF-8 encoding for Windows console
if sys.platform == "win32":
    sys.stdout.reconfigure(encoding="utf-8")

model = ChatGoogleGenerativeAI(model="gemini-3-flash-preview")

Important

MCP tool loading is asynchronous, so the agent functions are async and run inside asyncio. The sys.stdout.reconfigure(encoding="utf-8") line is Windows-specific and prevents UnicodeEncodeError when the model returns emoji.

Loading the MCP Tools

MultiServerMCPClient takes the server config and exposes the server's tools through get_tools(). We append the local web-search and weather tools to the MCP tools:

PYTHON
async def get_tools():
    client = MultiServerMCPClient(
        {
            "airbnb": {
                "command": "npx",
                "args": ["-y", "@openbnb/mcp-server-airbnb", "--ignore-robots-txt"],
                "transport": "stdio",
            }
        }
    )

    mcp_tools = await client.get_tools()
    tools = mcp_tools + [base_tools.web_search, base_tools.get_weather]

    print(f"Loaded {len(tools)} Tools")
    return tools

The System Prompt

The agent's behavior is driven by a focused system prompt (stored in scripts/prompts.py as AIRBNB_PROMPT). It instructs the agent to search immediately, use sensible defaults, present the top five results with links, and proactively check weather and attractions:

PYTHON
AIRBNB_PROMPT = """
You are a travel planning assistant.

Instructions:
- Search Airbnb listings immediately when user asks for accommodations
- Use defaults: adults=2, no dates if not specified
- Present top 5 results with link: https://www.airbnb.com/rooms/{listing_id}
- Use web_search for attractions, events, or travel info
- Use get_weather to check destination weather
- Be proactive, don't ask for details unless search fails
"""

Wiring and Running the Agent

Create the agent with the loaded tools and the system prompt, invoke it asynchronously, and print the final message:

PYTHON
async def hotel_search(query):
    tools = await get_tools()

    agent = create_agent(model=model, tools=tools, system_prompt=prompts.AIRBNB_PROMPT)

    result = await agent.ainvoke({"messages": [HumanMessage(query)]})

    response = result["messages"][-1].text
    print("\n============== Output =============")
    print(response)

Wrap it in a simple chat loop so you can ask follow-up questions from the terminal:

PYTHON
async def ask():
    print("\nChat mode started. Type 'q' or 'quite' to exit.\n")
    while True:
        query = input("You: ").strip()
        if query.lower() in ["q", "quite"]:
            print("Exiting chat mode.")
            break
        await hotel_search(query)


if __name__ == "__main__":
    asyncio.run(ask())

Run the script from the project root:

POWERSHELL
python "03 AI Projects/01_hotel_search_with_mcp/airbnb_mcp.py"

On Linux/macOS: the command is identical — python "03 AI Projects/01_hotel_search_with_mcp/airbnb_mcp.py".

Try a request that exercises all three tool sources at once:

PLAINTEXT
You: Show me hotels for a party in Pune, India. also check the latest news and weather.
PLAINTEXT
Loaded 4 Tools

============== Output =============
Here are 5 great Airbnb stays in Pune for your party, along with the current
weather and a couple of local updates:

1. Spacious 3BHK with terrace — https://www.airbnb.com/rooms/...
2. Luxury villa with private pool — https://www.airbnb.com/rooms/...
...

Weather in Pune: ~28°C, partly cloudy — pleasant for an evening gathering.
Latest news: <top headlines from web_search>

The agent searched Airbnb through MCP, then called get_weather and web_search in the same turn — a multi-source answer with no glue code beyond the server config.

Tip

Type your follow-ups directly: "find cheaper options under $50/night" or "what events are happening there this weekend?" The agent reuses the same tools to refine results.

You now understand MCP end to end and have a working agent that consumes a real MCP server. In the next lesson we add a second server and memory to build a full Travel Planner Agent with MCP & Memory that also writes to your Google Calendar.

Found this useful? Keep building with me.

New tutorials every week on YouTube — or go deeper with a full structured course.

Find this tutorial useful?

Subscribe to our YouTube channels for more practical production walk-throughs.

Discussion & Comments