obilet-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@obilet-mcpShow me bus trips from Istanbul to Ankara on 2026-11-07, cheapest first."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
obilet-mcp 🇹🇷
mcp-name: io.github.mohammad-abbasi-sh/obilet-mcp
Unofficial read-only MCP server for obilet.com**, Türkiye's bus & flight ticket search — search bus locations, list all bus journeys for a route + date (partner, bus type, seats, departure/arrival, duration, price in TRY, partner rating, stops), read full journey details, get price statistics, and read the flight summary (flight count, min/max price, airlines) for the same city pair.
Built by Mohammad Abbasi as part of the "Turkey MCP factory" (Sepehr-style pipeline). Not affiliated with obilet.com.
For AI agents
Add to your MCP client config (stdio):
{
"mcpServers": {
"obilet": {
"command": "uvx",
"args": ["obilet-mcp"]
}
}
}Or run locally: python -m obilet_mcp.server (needs mcp<2, curl-cffi).
Related MCP server: ultimate-travel-agent
Tools
Tool | Description |
| Search locations by name — |
| Bus journeys for a route + date — |
| Full detail of one journey ( |
| Price statistics for a route + date: journey count, min / median / mean / max ticket price in TRY |
| Flight summary for a route + date: flight count, min/max price in TRY, min/max duration, first/last departure, direct-flight flag, airlines with IATA codes (individual flight listings are NOT in v1) |
Example output (obilet_search_bus_journeys / İstanbul Avrupa -> Ankara, 2026-11-07):
{"origin_id": 349, "destination_id": 356, "date": "2026-11-07",
"sort": "price_asc", "total": 421, "count": 2, "journeys": [
{"journey_id": 1432053091, "partner": "Yükseller Aksaray Birlik",
"bus_type": "2+1", "total_seats": 41, "available_seats": 36,
"origin": "Esenler Otogarı", "destination": "Ankara (Aşti) Otogarı",
"departure": "2026-11-07T07:30:00", "arrival": "2026-11-07T15:30:00",
"duration": "08:00:00", "price_try": 539.0, "original_price_try": 700.0,
"price_currency": "TRY", "partner_rating": 8.64, …}, …]}Example output (obilet_flight_summary / same route & date):
{"origin_id": 349, "destination_id": 356, "date": "2026-11-07",
"flight_count": 26, "has_direct": true, "min_price_try": 1461.99,
"max_price_try": 7399.34, "min_duration": "01:00:00",
"max_duration": "12:05:00", "first_departure": "00:05:00",
"last_departure": "23:30:00",
"airlines": [{"name": "Pegasus", "iata": "PC"}, {"name": "AJet", "iata": "VF"},
{"name": "THY", "iata": "TK"}]}Example output (obilet_price_stats / same route & date):
{"origin_id": 349, "destination_id": 356, "date": "2026-11-07",
"count": 421, "min_try": 539.0, "median_try": 800.0,
"mean_try": 852.38, "max_try": 1150.0}How it works
obilet.com exposes a JSON API, but it is session-gated: an HTML page
is fetched first (it sets cookies incl. ob_Session and __cf_bm),
then POSTs carry X-Requested-With: XMLHttpRequest with that page as
Referer. Locations: POST /json/duraklar (bus) or /json/ucak-duraklari
(flight). Journeys: POST /json/journeys/{origin}-{destination}/{date}
with {} — one response holds every journey for the route. Detail:
POST /json/sefer-tam/{journeyId}. The same journeys response carries
the flightSummary. Sorting is client-side (price / departure /
duration). The async flights endpoint is broken on the site side
(404/500), so individual flight listings are out of scope for v1.
Transport uses a persistent curl-cffi chrome120 session; requests are
spaced ~0.8s apart; everything is read-only, no login, no API key.
Install
uvx obilet-mcp # run directly (needs uv)
# or
pip install obilet-mcp
obilet-mcp # starts the MCP server on stdioTests
python -m venv .venv && .venv/bin/pip install -e .
.venv/bin/python -m unittest discover -s tests -vOffline tests run on recorded fixtures (real pages fetched 2026-11-06); live tests hit obilet.com.
Roadmap
Individual flight listings (if the async flights endpoint is fixed)
Round-trip search (outbound + return in one call)
Seat-map / available-seat detail per journey
License
MIT — see LICENSE.
Available Tools
5 toolsobilet_flight_summaryA
Flight summary for a route + date (from the bus-journeys response): flight count, min/max price in TRY, min/max duration, first/last departure, direct-flight flag and airlines with IATA codes. origin_id / destination_id: bus location ids (the summary covers the same city pair); date: YYYY-MM-DD. Note: individual flight listings are NOT available in v1 (the async flights endpoint is broken on the site side).
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| origin_id | Yes | ||
| destination_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the burden, and it does disclose the key behavioral fact: this is a derived summary and per-flight detail is unavailable due to a server-side breakage. It also describes the aggregate return shape. It does not mention auth requirements, rate limits, or expected latency, which is why it falls short of 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then parameter semantics, then the critical limitation note — a sensible ordering with little waste. The long enumeration of returned fields is somewhat redundant given an output schema exists, which keeps it from a top score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-required-param aggregate tool with an output schema and no annotations, the description covers purpose, inputs, and the major v1 limitation. The one remaining gap an agent might hit is how to obtain valid location ids, which is only implied by "bus location ids".
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% (bare titles only), so the description must compensate, and it does: origin_id/destination_id are identified as bus location ids covering the same city pair, and date is pinned to YYYY-MM-DD. That resolves the main ambiguity an agent would face — that despite being a flight tool, the ids are bus-domain identifiers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific resource and scope up front: "Flight summary for a route + date" with the exact fields returned (counts, min/max price, durations, departures, direct flag, airlines). The parenthetical that it comes from the bus-journeys response distinguishes it from obilet_search_bus_journeys and obilet_journey_detail, so an agent can tell what it is without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear usage context by naming the city-pair scope and warning that individual flight listings are NOT available in v1 because the async endpoint is broken — that prevents a whole class of wrong attempts. It stops short of naming an explicit alternative (e.g. "use obilet_search_bus_journeys for the raw data") or saying the location ids must first come from obilet_search_locations, so it is not a full when/when-not map.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
obilet_journey_detailA
Full detail of one bus journey: partner, bus type, seats, origin/destination stations, departure/arrival, duration, internet price and original price in TRY, service fee, partner rating, bus name, platform (peron), description and every stop with its time. journey_id: from obilet_search_bus_journeys.
| Name | Required | Description | Default |
|---|---|---|---|
| journey_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden; it implies a read-only lookup and discloses that prices are quoted in TRY with a separate service fee and original price, which is genuinely useful. It never states whether availability/prices are live, whether results are cached, or any auth or rate-limit behavior, so an agent cannot fully predict the call's side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the one-line purpose, then a dense field inventory, with the id provenance moved to the end where it belongs. The field enumeration borders on redundant since an output schema exists, and the run-on list is slightly hard to scan, but there is little wasted wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter lookup with an output schema present, this is largely sufficient: it explains the input's origin and signals the breadth of the return payload. The remaining gap is failure behavior for an invalid or expired journey_id, which the description does not address.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate; it does the most important thing by telling the agent where the opaque journey_id originates (obilet_search_bus_journeys). It does not add the integer type or say whether the id is stable across dates, but provenance is the key semantic gap and it is covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Full detail of one bus journey', then enumerates exactly what comes back (partner, stations, times, prices in TRY, stops). This clearly separates it from the list-oriented obilet_search_bus_journeys, though it never names that sibling as the alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The clause 'journey_id: from obilet_search_bus_journeys' does convey the required prerequisite (search first, then fetch detail), which is real usage guidance. However, there is no explicit when-to-use vs when-not, and no statement about what to do if the journey is no longer bookable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
obilet_price_statsB
Price statistics for a bus route + date: journey count, min / median / mean / max ticket price in TRY across all journeys. origin_id / destination_id: bus location ids; date: YYYY-MM-DD.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| origin_id | Yes | ||
| destination_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden. It does disclose the aggregation semantics ('across all journeys'), the currency (TRY), and the computed statistics, which is real behavioral value; however it says nothing about whether it is a read-only query, how it behaves when no journeys exist, or whether results are cached or limited to certain carriers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with the returned metrics front-loaded and parameter notes second; no filler and no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple three-required-parameter aggregate query with an output schema, the description covers purpose, returned metrics, and parameter formats adequately. The remaining gap is id provenance — how to resolve origin_id and destination_id — which an agent must guess from the sibling list.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% — the schema gives only bare titles — so the description must compensate. It supplies the date format (YYYY-MM-DD) and characterizes origin_id/destination_id as bus location ids, which is useful, but it does not say where those ids come from (presumably obilet_search_locations) or whether they denote cities versus terminals.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (price statistics for a bus route + date) and enumerates exactly which statistics are returned (journey count, min/median/mean/max price in TRY). This clearly distinguishes it from obilet_search_bus_journeys, which lists individual journeys rather than aggregates, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use or when-not-to-use guidance and no mention of alternatives such as obilet_search_bus_journeys or obilet_journey_detail. The aggregate purpose implies a cheap overview use case, but the agent must infer that entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
obilet_search_bus_journeysA
Bus journeys for one route + date. origin_id / destination_id: bus location ids from obilet_search_locations (e.g. İstanbul Avrupa 349 -> Ankara 356). date: YYYY-MM-DD (e.g. "2026-11-07"). sort: "price_asc" (cheapest first, default), "departure" (earliest first), "duration" (shortest first). limit 1..24. Returns journey id, partner, bus type, seats, origin/destination stations, departure/arrival, duration, price in TRY, partner rating (0-10) and stops per journey, plus the total count for the route.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| sort | No | price_asc | |
| limit | No | ||
| origin_id | Yes | ||
| destination_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does disclose meaningful behavior: the default sort (
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The structure is good: the resource/scope line comes first, then a compact per-parameter block, then the return payload. It is dense but every clause carries information; only the trailing return-field enumeration is slightly verbose given an output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter search tool with a declared output schema, nothing an agent needs in order to call it correctly is missing: id provenance, date format, sort options, and limit bounds are all stated. Return values are described even though the output schema already covers them, which is surplus rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate and it does: origin_id/destination_id are explained as bus location ids with a worked example, date is pinned to YYYY-MM-DD with a sample, sort is given all three enum values with their ordering semantics and the default, and limit is bounded to 1..24. That covers all five parameters with meaning the bare schema does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-and-resource statement ('Bus journeys for one route + date'), so the agent immediately knows this is a route/date search over bus inventory. It explicitly points at obilet_search_locations for the id source, but it never distinguishes itself from siblings like obilet_journey_detail or obilet_price_stats, which keeps it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives one real prerequisite: origin_id/destination_id must come from obilet_search_locations, illustrated with a concrete İstanbul Avrupa 349 -> Ankara 356 example. Beyond that there is no when-to-use versus when-not guidance, no mention of when to prefer obilet_journey_detail (for a specific journey) or obilet_price_stats (for price trends), so the selection logic across siblings is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
obilet_search_locationsA
Search obilet.com locations (cities, towns, airports) by name. query: e.g. "Ankara", "İstanbul", "İzmir". kind: "bus" (default, int ids) or "flight" (string ids like "250_0"). Returns id, name, display name and city id per match. Use the id in obilet_search_bus_journeys (bus) or obilet_flight_summary (flight).
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | bus | |
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the behavioral burden. It does disclose a real quirk — bus ids are ints while flight ids are strings like "250_0" — and names the returned fields, but it says nothing about matching behavior (partial vs exact, Turkish character handling), result limits, or authentication needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded in the first sentence, followed by compact per-parameter notes and a closing routing hint. There is no filler; every clause, including the example ids, conveys usable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the brief return-field mention is a bonus rather than a requirement, and both parameters are addressed despite zero schema coverage against a 2-parameter tool. The only shortfall for a search tool is the absence of guidance on match quality and ambiguity handling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it largely does: query is illustrated with concrete city examples, and kind is documented with both allowed values, the default, and the associated id type per mode. It still omits match semantics and whether an empty or ambiguous query is an error.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource plus scope: search obilet.com locations (cities, towns, airports) by name. That is far more than the tool name alone and tells an agent exactly what kind of entity is resolved here versus the journey/detail siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly routes the agent forward: use the returned id in obilet_search_bus_journeys for bus or obilet_flight_summary for flight, and the kind parameter selects which. There is no explicit when-not-to-use or note about calling this without a downstream lookup, but the workflow context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
obilet_flight_summary - First observed
obilet_journey_detail - First observed
obilet_price_stats - First observed
obilet_search_bus_journeys - First observed
obilet_search_locations
TDQS
Scored across 5 tools
Each tool has a recognizable role: location lookup, bus journey search, journey detail, aggregate price stats, and flight summary. The main soft overlap is between obilet_price_stats and obilet_search_bus_journeys, since both take route+date and prices already appear in journey results, and price_stats is bus-only while flight_summary also reports price ranges. Descriptions do clarify the distinction (aggregate vs. listings), so confusion is limited.
All five tools share the obilet_ prefix and snake_case, which makes the set predictable and easy to scan. The only inconsistency is verb style: search_locations and search_bus_journeys lead with a verb, while price_stats, journey_detail, and flight_summary are noun-first phrases. It is still readable but not a strict verb_noun pattern.
Five tools is well within a healthy range for a read-only travel search domain. Each tool covers a distinct step (resolve locations, list journeys, inspect a journey, aggregate prices, summarize flights) with no filler tools. Nothing feels padded or conspicuously missing at the count level.
The surface supports the core workflow: find location ids, search bus journeys, drill into a journey, get price statistics, and get a flight overview. Gaps exist but are documented—no individual flight listings (explicitly broken upstream in v1) and no booking/purchase or advanced filtering on bus results. Agents can work around these within the stated informational purpose.
Maintenance
Related MCP Connectors
Free web search, 130M+ business records, local search, weather and travel data for AI agents.
Open places, menus, ratings and booking routes in 119 travel destinations. Read-only, no key needed.
Read-only Istanbul open city data: transport, parking, water, nearby services and datasets.
Read-only lookups of public AI agent pricing, free plans and source links. No API key.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables searching Turkish high-speed train (YHT) tickets via TCDD API. Supports real-time availability, station name resolution, date formatting, and passenger count.MIT
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to access 21 read-only tools for local travel planning, including trip and itinerary validation, budget calculation, booking requirements, integration provider status, flight/train/accommodation/activity searches, route/weather/currency lookups, and travel source search.MIT
- AlicenseAqualityAmaintenanceEnables AI agents to search and compare the cheapest flights, trains, buses, private taxis and hotels across Iran, including free seats, baggage allowances, refund rules and exact prices, for a single date or across weeks. All 22 tools are read-only and return compact structured JSON, so an agent can plan multi-mode trips and hotel stays without logging in or booking.2222120 PyPI2MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to compare and find the cheapest domestic and international flights, hotels, villas, trains and buses in Iran, with exact Toman prices, fare and cancellation rules, baggage details, seats left and hotel reviews. Also covers CIP lounges, eSIM plans, visas and tours, and is read-only, so it never books, holds seats or pays.329 PyPI2MIT