This lesson connects Kiwi's remote MCP server to a LangChain Agent, letting the Agent call flight-search tools while using thread_id to preserve memory for one conversation.
The previous lesson used stdio to start a local MCP server. This lesson switches to a remote MCP server: Kiwi provides flight-related tools over the network, and the Agent does not need to know how Kiwi implements them.
| Comparison | Local stdio MCP | Remote MCP |
|---|---|---|
| Connection method | command + args start a subprocess | url connects to a remote service |
| Best for | Local scripts, internal tools, development debugging | Third-party platforms, cloud services, shared capabilities |
| Example in this lesson | resources/2.1_mcp_server.py | https://mcp.kiwi.com |
The notebook uses MultiServerMCPClient to connect to travel_server. The returned tools become the external capabilities for the travel Agent.
client = MultiServerMCPClient(
{
"travel_server": {
"transport": "sse",
"url": "https://mcp.kiwi.com",
}
}
)
tools = await client.get_tools()sse means connecting to the remote MCP server through Server-Sent Events. Later lessons also use streamable_http.
Before giving tools to the Agent, printing their names is a practical debugging step. It confirms that the connection worked and helps you understand which actions the model can call.
for msg in tools:
pprint(msg.name)
print()Remote MCP tool sets can change. Inspect the tool names and descriptions before writing the system prompt to reduce the chance that the model misuses a tool.
The travel Agent has three core configuration pieces: model, MCP tools and checkpointer. InMemorySaver lets conversations with the same thread_id retain context.
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(
deepseek_model(),
tools=tools,
checkpointer=InMemorySaver(),
system_prompt="You are a travel agent. No follow up questions.",
)Flight-search capabilities provided by Kiwi MCP.
Saves message history and state in the same thread.
Asks the Agent to act as a travel agent and avoid follow-up questions.
For the actual call, the notebook uses ainvoke and configurable.thread_id. This lets one travel-planning request be associated with later conversation turns.
config = {"configurable": {"thread_id": "1"}}
response = await agent.ainvoke(
{
"messages": [
HumanMessage(
content="Get me a return flight from Melbourne to Changsha on Sep 1st 2026 and return on Sep 18st 2026."
)
]
},
config,
)
print(response["messages"][-1].content)Flight tools are usually sensitive to dates, airports, passenger counts and similar parameters. "No follow up questions" in the system prompt forces the model to search from available information, but missing parameters can make results less stable.