Maitabi (Python)
Search Maitabi (まいたび — 毎日新聞旅行 / 毎日あるぺん号) from one package: mountain bus tours (bus.maitabi.jp), general travel and trekking tours, and departure calendars (www.maitabi.jp). It ships as a CLI, an MCP server, and three agent skills — all driven by the same eight actions.
Unofficial client. Not affiliated with 毎日新聞旅行.
| Interface | Use it when | Start with |
|---|---|---|
| CLI | you want commands, scripts, or JSON for jq |
uvx maitabi --help |
| MCP server | you want the tools inside an MCP client | uvx maitabi mcp |
| Skills | you want an agent to know the workflows | npx skills add phonhay103/maitabi -g |
Install
uv tool install maitabi # installs the `maitabi` command on your PATH
uv tool upgrade maitabi # later, to update it
maitabi --version # confirm which version is running
Nothing installed? uvx maitabi ... runs the same published version on demand, e.g. uvx maitabi bus search-tours --month 11.
Quick start (CLI)
# Mountain bus tours
maitabi bus search-tours --month 11 --area 18 --pretty
# General trekking tours
maitabi general search-tours --travel-type 1 --keyword '富士山' --year-month 2026-11
# One tour in full
maitabi bus get-tour-detail --course-no 14241
# Monthly departure matrix
maitabi general get-calendar --year 2026 --month 11 --travel-type 1
Every data command accepts --pretty and --output FILE.
Output contract
Search commands return one envelope; every item carries a detail_url:
{
"count": 191,
"page": 1,
"items": [
{
"course_no": 14241,
"course_cd": "S104C21",
"date": "2026年09月12日(土)",
"title": "立山室堂ライン往復ツアー",
"price": "15,500円",
"status": "受付中",
"detail_url": "https://bus.maitabi.jp/detail.html?course_no=14241&year=2026&month=9"
}
],
"query": { "departure": 1, "month": 11, "page": 1 }
}
countis the upstream total for the query, before the client-side price/availability filters;itemscan be shorter on the current page.countandpagearenullwhen upstream does not report them;itemsis always a list.- Batch detail (
--course-no 14241,8518) returns the same envelope withpage: null; a single course returns the detail object itself. - Filter options, district groups, and the calendar return their own objects — a list of one would add indexing without information.
statusis domain-native: a Japanese string for bus, a numeric code for general (1/2 bookable, 3 closed).- Errors are always
{"error": ..., "detail": ...}, never a partial envelope.
The contract only grows: new fields appear, existing ones are never renamed or removed within a major version.
Tools (7)
Full parameter reference (MCP args, CLI flags, defaults, endpoints): docs/TOOL_CATALOG.md — generated from the code, so it cannot drift.
Mountain bus (api.bus.maitabi.jp)
| MCP tool | CLI | What it does |
|---|---|---|
bus_list_filters |
maitabi bus list-filters |
filter options, lodges, tour counts (cascading) |
bus_list_district_groups |
maitabi bus list-district-groups |
area/district groups + counts |
bus_list_filter_master |
maitabi bus list-filter-master |
one master list (--kind style|bus_sheet|return_day|district), small payload |
bus_search_tours |
maitabi bus search-tours |
search tours and lodge packages |
bus_get_tour_detail |
maitabi bus get-tour-detail |
full itinerary by course_no (single or batch) |
General tours & calendar (www.maitabi.jp)
| MCP tool | CLI | What it does |
|---|---|---|
general_search_tours |
maitabi general search-tours |
search by travel_type 1-5, keyword, dates, categories |
general_get_tour_detail |
maitabi general get-tour-detail |
itinerary, conditions, every departure + booking link |
general_get_calendar |
maitabi general get-calendar |
monthly departure matrix |
One deliberate exception to "API only"
www.maitabi.jp publishes no tour-detail API — api/v1 serves only category_search and calendar/{year}/{month}, and api.bus.maitabi.jp only knows mountain-bus courses. So general_get_tour_detail reads the rendered detail page, in a way that keeps the fragile surface small:
- the tour record itself (title, description, price, statuses) comes from a JSON literal the page embeds (
const detailData = {...}), parsed as JSON — no prose is scraped; - only three
<table>elements are read from the markup: itinerary, travel conditions, and the departure/price matrix. Columns are matched by their Japanese headers, not by position.
If the page ever loses that structure the tool returns an error naming source_url instead of a hollow object, and the offline fixtures in tests/fixtures/ fail first.
MCP server
One executable, one subcommand. mcp speaks stdio by default, or sse / streamable-http:
uvx maitabi mcp # stdio — what MCP clients expect
uvx maitabi mcp --transport streamable-http --port 8000
docker run -i --rm phonhay103/maitabi mcp # same thing in a container
Client configuration (mcpServers key):
{
"mcpServers": {
"maitabi": {
"command": "uvx",
"args": ["maitabi", "mcp"]
}
}
}
Docker variant:
{
"mcpServers": {
"maitabi": {
"command": "docker",
"args": ["run", "-i", "--rm", "phonhay103/maitabi:latest", "mcp"]
}
}
}
Local checkout, no install:
{
"mcpServers": {
"maitabi": {
"command": "uv",
"args": ["run", "--directory", "/path/to/maitabi", "maitabi", "mcp"]
}
}
}
Tools are named <domain>_<command>: bus_* reads api.bus.maitabi.jp, general_* reads www.maitabi.jp.
Agent skills
npx skills add phonhay103/maitabi -g # all three
npx skills add phonhay103/maitabi --list # inspect first
maitabi-cli— terminal workflows and JSON piping.maitabi-mcp— how to call the already-connected tools: which tool, in what order, how to read results.maitabi-bus-extractor— raw HTTP/curl for both hosts, standalone. No CLI, no MCP.
Rate limits
| Host | Limit | Applies to |
|---|---|---|
www.maitabi.jp |
60 requests/min per IP | general tours + calendar |
api.bus.maitabi.jp |
none observed at normal usage | mountain bus tours |
When the cap is hit, the result is {"error": "Rate limited by www.maitabi.jp ...", "retry_hint": "wait ~60s and retry manually"}. There is no auto-retry. Narrow --day ranges help, since each day fans out into a parallel request (bounded at 5).
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Upstream/network error (payload contains error, incl. rate limiting) |
| 2 | Input error (bad flag value or failed validation) |
Development
make install # uv sync
make dev # MCP server over stdio
make test # offline suite (no network)
make smoke # live check against the production API
make catalog # regenerate docs/TOOL_CATALOG.md + skill reference copies
make catalog-check # what CI runs — fails on stale generated files
make docker-build # 2-stage image (Python 3.14)
make build # wheel + sdist
Architecture, in one paragraph: parameters live once in core/inputs.py; endpoint logic lives in services/; registry.py declares one Action per capability (domain, MCP tool name, CLI command, input model, service, endpoint, docs); both adapters and the catalog are generated from that table, so the CLI, the MCP schema, and the documentation cannot disagree. See AGENTS.md.
Links
Metadata
Release files for maitabi 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| maitabi-1.2.0.tar.gz | 163.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| maitabi-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 205.1 kB
Release files / maitabi-1.2.0.tar.gz
| Download URL | maitabi-1.2.0.tar.gz |
|---|---|
| Size | 163.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4325d83382f5b7820ae6682ff131c527fe0cf20eefc1743b9891d0db9003c6e9
|
|
BLAKE2b-256 checksum How to use checksums |
30d74ced51a3f4a73c279a61979615c207614084e6164d329aeb9e30679fd91b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / maitabi-1.2.0-py3-none-any.whl
| Download URL | maitabi-1.2.0-py3-none-any.whl |
|---|---|
| Size | 41.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c9b683851495e514463a0607fce563a318d39f34a609ef7065d414f14a2a06f
|
|
BLAKE2b-256 checksum How to use checksums |
9a743ed99c0acf7b1ae8b059c4ab40860ce4de491e82546d923912a69a5e3c04
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for maitabi 1.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for maitabi-1.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.