italian-bus-search
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., "@italian-bus-searchFind one-way buses from Rome to Milan on 15 June"
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.
Italian Bus Search
An unofficial, read-only TypeScript service that searches multiple Italian coach operators through HTTP and Model Context Protocol interfaces.
The project hides provider-specific station catalogs, request formats, fare structures, and multi-leg responses behind one shared application core. It never performs login, booking, seat selection, or payment operations.
This project is not affiliated with or endorsed by Itabus, Autoservizi Salemi, Autolinee Federico, or MarinoBus. Provider names and trademarks belong to their owners. Before enabling a live adapter, confirm that your use complies with the provider's terms, applicable law, and any required authorization. This repository does not grant data-extraction or redistribution rights.
Features
One response model for locations and journeys across different booking platforms.
Live adapters for four operators.
Partial results when one provider fails and another succeeds.
A local stdio MCP server with structured, read-only tools.
Official links for continuing a search manually on provider sites.
Structured, provider-scoped errors instead of leaked upstream responses.
Five-second upstream timeouts.
One-hour location caches and 60-second journey caches.
Per-client in-memory rate limiting at 60 requests per minute.
Offline tests with synthetic fixtures; the test suite never contacts provider sites.
A small runtime dependency surface: the official MCP SDK and Zod.
Related MCP server: soloway-mcp
Supported providers
Provider ID | Operator | Integration | Locations | Journeys |
| Itabus | Demandware endpoints | Live | Live |
| Autoservizi Salemi | Albatross tenant | Live | Live |
| Autolinee Federico | Albatross tenant | Live | Live |
| MarinoBus | Albatross tenant | Live | Live |
Provider behavior and the evidence behind each integration are recorded in Provider research.
Requirements
Node.js 22.18 or newer
npm
Quick start
git clone https://github.com/Alexxanddr/italian-bus-search.git
cd italian-bus-search
npm install
cp .env.example .env
npm startThe server listens on http://127.0.0.1:3000 by default.
curl http://127.0.0.1:3000/health
curl http://127.0.0.1:3000/providers
curl 'http://127.0.0.1:3000/locations?query=Roma&provider=marinobus'For journey searches, use a real future date:
curl 'http://127.0.0.1:3000/journeys?origin=Roma&destination=Milano&date=YYYY-MM-DD&adults=1&children=0&provider=marinobus'YYYY-MM-DD is a placeholder and must be replaced before running the command.
HTTP interface
Method | Path | Purpose |
|
| Process liveness |
|
| Adapter status and operational reason |
|
| Provider location search |
|
| Normalized one-way journey search |
/locations and /journeys accept an optional provider parameter. Without it, all providers are queried independently and successful data is preserved alongside provider-scoped errors.
The complete parameter, response, status, and error contract is in HTTP interface.
MCP server
The simplest MCP configuration runs the published package directly with npx:
{
"mcpServers": {
"italian-bus-search": {
"command": "npx",
"args": ["-y", "italian-bus-search@latest"]
}
}
}Alternatively, build and start the local stdio server:
npm run build
npm run mcp:builtIt exposes list_providers, search_locations, and search_journeys. A host model can turn “find buses from Rome to Milan on 15 November” into the location and journey tool calls, then show normalized options with official links for manual purchase.
{
"mcpServers": {
"italian-bus-search": {
"command": "node",
"args": ["/absolute/path/to/italian-bus-search/dist/mcp/stdio.js"]
}
}
}See MCP interface for the authoritative tool contract, limits, errors, and development command.
Architecture
The application has four layers:
HTTP and MCP adapters validate their transport-specific requests;
shared validation and
SearchServiceorchestrate searches and partial results;each provider adapter translates a remote protocol into domain types;
the domain module owns normalized data and error contracts.
Provider adapters implement one shared interface, so callers do not know whether a result came from Itabus Demandware or an Albatross tenant. See Architecture for modules, seams, data flow, caches, and test strategy.
Development
npm run dev
npm run mcp
npm run checknpm run check runs the complete offline test suite, TypeScript type checking, and the configured lint check. To add an operator, follow Adding a provider; do not infer a new integration from HTML alone or copy credentials into fixtures.
Deployment
The default server deliberately binds to loopback and keeps rate-limit and cache state in process memory. Read Operations before placing it behind a reverse proxy or running multiple replicas.
Project documentation
HTTP interface — authoritative endpoint and error contract.
MCP interface — authoritative tools, results, limits, and stdio contract.
Architecture — modules, seams, flows, and design decisions.
Adding a provider — research, implementation, and verification checklist.
Operations — configuration, deployment constraints, and failure handling.
Provider research — primary-source evidence and known limitations.
Glossary — stable project terminology.
Contributing — local workflow and pull-request expectations.
Security policy — private vulnerability reporting and supported versions.
Agent instructions — compact routing instructions for coding agents.
Scope and limitations
Searches are one-way only.
Availability is a provider-reported signal, not a seat or price guarantee.
Prices and schedules can change between search and purchase.
Caches and rate limits reset when the process restarts and are not shared across replicas.
Upstream interfaces are unofficial and can change without notice.
Both interfaces intentionally exclude accounts, bookings, payments, and CAPTCHA handling.
Always complete and confirm a purchase on the official provider site linked by bookingUrl.
Contributing and security
Contributions are welcome; start with CONTRIBUTING.md. Report vulnerabilities privately according to SECURITY.md, not through a public issue.
License
Source code is available under the MIT License. The license covers this repository's code, not third-party data, provider trademarks, or access rights to upstream systems.
Available Tools
3 toolslist_providersList Italian bus providersARead-onlyIdempotent
List configured journey providers and their status without contacting provider systems.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| providers | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent and non-destructive. The description adds the non-obvious point that no provider systems are contacted, which qualifies the openWorldHint and tells the agent this is fast and cannot fail on network or availability.
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?
A single front-loaded sentence with zero filler; the behavioral caveat is packed into the same clause rather than padding the definition.
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 return shape ('providers and their status') need not be spelled out. For a no-parameter read-only tool the description covers everything needed to call it correctly.
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?
The tool takes no parameters and the schema is trivially complete, so there is nothing for the description to clarify. Baseline 4 applies to zero-parameter tools.
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 ('List configured journey providers and their status'), and the title narrows it to Italian bus providers. It implicitly separates configuration introspection from the sibling search tools, though it never names them.
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 phrase 'without contacting provider systems' implies this is a cheap local config read, useful for checking what is configured before a search. However, it never explicitly says when to call this versus search_journeys or search_locations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_journeysSearch Italian bus journeysARead-onlyIdempotent
Search one-way journeys. Use origin and destination IDs or exact names returned by search_locations. Results include official links for continuing manually on provider sites.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | Real future date in YYYY-MM-DD format | |
| limit | No | ||
| adults | No | ||
| origin | Yes | Exact location name or ID returned by search_locations | |
| children | No | ||
| provider | No | Provider ID; omit to search every provider | |
| destination | Yes | Exact location name or ID returned by search_locations |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | Yes | |
| errors | Yes | |
| journeys | Yes | |
| truncated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, open-world, non-destructive, so the safety profile is covered. The description adds genuinely useful context beyond that: results are informational and include official provider links for manual continuation, making clear the tool does not book or transact.
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?
Three short sentences, front-loaded with the action, followed by the prerequisite and the result shape. No filler or 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?
An output schema exists, so return values need not be explained, and the description still notes the useful link payload. Combined with annotations and a 57%-covered schema, only minor gaps remain (passenger/limit semantics, date validity), which the schema largely carries.
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 57%, with origin/destination/date already documented in the schema. The description reinforces the origin/destination format convention but says nothing about provider, adults, children, or limit, so it adds only marginal meaning over the structured fields.
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 ("Search one-way journeys") and the title narrows it to Italian bus journeys. It implicitly distinguishes itself from search_locations by naming that sibling as the source of valid origin/destination values, though it does not explicitly contrast with list_providers.
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 a clear prerequisite: origin/destination must be IDs or exact names returned by search_locations, which tells the agent to call that tool first. There are no explicit exclusions or when-not-to-use conditions, but the calling context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_locationsSearch Italian bus locationsARead-onlyIdempotent
Find provider location IDs and exact names. Call this before search_journeys, then reuse an ID or exact name from the result.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | Partial city, stop, or location name | |
| provider | No | Provider ID; omit to search every provider |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | Yes | |
| errors | Yes | |
| locations | Yes | |
| truncated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and open-world, so the safety profile is covered. The description adds genuinely new behavioral context: this is a prerequisite step whose results must be fed into search_journeys as an ID or exact name, which is the key constraint an agent needs. It does not mention partial-match semantics or result cap behavior, so it stops short of full transparency.
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 sentences, zero filler, with the purpose front-loaded and the workflow instruction second. Every clause carries actionable 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 return-format explanation is unnecessary, and the description covers purpose plus the chaining dependency. It could do slightly more for the provider/limit parameters, but nothing critical to a correct call is missing.
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 67% — query and provider are documented inline, but limit is not. The description adds no parameter-level detail (no mention of limit, provider omission, or matching rules), so it does not compensate for the uncovered parameter. Baseline 3 applies when the schema carries most of the load.
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 (find location IDs and exact names), and the emphasis on IDs/exact names distinguishes it from search_journeys, which returns trips rather than locations. It never names list_providers as a related lookup, so sibling differentiation is partial rather than complete.
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?
'Call this before search_journeys' gives an explicit ordering constraint and tells the agent how to consume the output (reuse an ID or exact name). What's missing is guidance on the provider parameter — e.g., that list_providers supplies valid provider IDs — so one branch of usage is left implicit.
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.
3 tool updates
v0.1.2- First observed
list_providers - First observed
search_journeys - First observed
search_locations
TDQS
Scored across 3 tools
Each tool covers a distinct step: listing providers (configuration), resolving locations to IDs, and searching journeys. The descriptions explicitly state the ordering dependency (call search_locations before search_journeys), leaving no room for misselection.
All three tools follow a strict verb_noun pattern (list_providers, search_locations, search_journeys) in consistent snake_case. The 'search_' prefix is used coherently for the two query tools and 'list_' for enumeration.
Three tools is minimal but each occupies a necessary stage of the search pipeline, with no filler. It sits at the thin edge of the range, but the narrow single-purpose domain justifies it.
The surface covers provider discovery, location resolution, and one-way journey search, forming a coherent lifecycle, but only one-way trips are supported — no round-trip or return-date search, and no way to fetch details for a specific journey beyond the search result.
Maintenance
Related MCP Connectors
AI marketplace — flights, tours, activities, transport & more via MCP. No auth required.
The Ferryhopper MCP server is a connector for LLMs and AI Agents in maritime travel that exposes ferry routes, schedules, and booking options. It enables AI assistants to search ports and connections across 33 countries and 190+ ferry operators, provide real-time ferry itineraries with indicative prices, and assist users with planning island-hopping or multi-leg journeys by processing natural language queries about ferry times, passenger counts, and travel durations.
Search and compare flight offers through a cache-aware Streamable HTTP MCP server for AI agents.
Live Google Maps business search, review, and photo data for AI agents over MCP.
Related MCP Servers
- AlicenseAqualityDmaintenanceReal-time train, bus, ferry and private transfer prices between 40+ Italian cities4MIT
- AlicenseNot gradedqualityCmaintenanceLive intercity bus-trip search across Ukraine and Europe — real-time prices, seats, carriers, cheapest-day-of-month calendar, and trip details with passenger discounts. Read-only, no API key; also available as a hosted remote endpoint at https://mcp.soloway.com.ua/mcp.MIT
- AlicenseNot gradedqualityBmaintenanceEnables searching for buses and trains, and when direct routes are unavailable, it provides the underlying data needed to assemble multi-leg itineraries with transfers.6 npmISC

virail-mcpofficial
AlicenseAqualityBmaintenanceEnables MCP-compatible AI agents to search live Virail transport connections across trains, buses, flights, ferries, and carpooling, returning real prices, schedules, and booking links.1MIT