Metadata-Version: 2.5
Name: maitabi
Version: 1.0.1
Summary: Maitabi (unofficial): bus tours, trekking tours and calendars as a CLI, an MCP server, and agent skills
Project-URL: Homepage, https://github.com/phonhay103/maitabi
Project-URL: Repository, https://github.com/phonhay103/maitabi
Project-URL: Docker Hub, https://hub.docker.com/r/phonhay103/maitabi
Author-email: phonhay103 <phonhay103@users.noreply.github.com>
License: Apache-2.0
License-File: LICENSE
Keywords: bus-tour,fastmcp,japan-travel,maitabi,mcp,model-context-protocol
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Requires-Dist: fastmcp>=3.4.5
Requires-Dist: httpx>=0.27.0
Requires-Dist: mcp>=1.29.0
Requires-Dist: pydantic>=2.13.4
Description-Content-Type: text/markdown

# 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 seven 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` |

## Quick start (CLI)

```bash
# 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
```

Install permanently with `uv tool install maitabi` or `pip install maitabi`. Every data command accepts `--pretty` and `--output FILE`.

## Output contract

Search commands return one envelope; every item carries a `detail_url`:

```json
{
  "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 }
}
```

- `count` is the upstream total for the query, **before** the client-side price/availability filters; `items` can be shorter on the current page.
- `count` and `page` are `null` when upstream does not report them; `items` is always a list.
- Batch detail (`--course-no 14241,8518`) returns the same envelope with `page: 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.
- `status` is 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`](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_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, meals, guide, booking links |
| `general_get_calendar` | `maitabi general get-calendar` | monthly departure matrix |

## MCP server

One executable, one subcommand. `mcp` speaks `stdio` by default, or `sse` / `streamable-http`:

```bash
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):

```json
{
  "mcpServers": {
    "maitabi": {
      "command": "uvx",
      "args": ["maitabi", "mcp"]
    }
  }
}
```

Docker variant:

```json
{
  "mcpServers": {
    "maitabi": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "phonhay103/maitabi:latest", "mcp"]
    }
  }
}
```

Local checkout, no install:

```json
{
  "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

```bash
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

```bash
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`](AGENTS.md).

## Links

- PyPI: <https://pypi.org/project/maitabi/>
- Docker Hub: <https://hub.docker.com/r/phonhay103/maitabi>
- Source: <https://github.com/phonhay103/maitabi>
