📚 Documentation: https://narumiruna.github.io/gurume/
Gurume is a Python library, CLI, TUI, and MCP server for discovering Japanese restaurants on Tabelog — Japan's largest restaurant review platform.
Search by area, cuisine, date, and party size; parse structured detail pages; and plug the same workflows directly into AI assistants via a FastMCP server.
- 🔍 Search restaurants by area, keyword, cuisine, date, time, and party size
- 🍣 Filter by 45+ supported Japanese cuisine categories with stable Tabelog genre codes
- 📄 Parse restaurant detail pages into structured review, menu, and course data
- ⚡ Use synchronous and asynchronous Python APIs
- 🖥️ Run an interactive TUI with area suggestions, keyword suggestions, and AI-assisted query parsing
- 🤖 Start an MCP server with schema-first inputs and structured outputs for AI assistant integrations
- 🔒 Keep responses typed with Pydantic models and Python type hints
uv add gurumeOr with pip:
pip install gurumeFor local development:
uv sync --devThe built-in CLI currently exposes four commands:
gurume searchgurume list-cuisinesgurume tuigurume mcp
Examples:
# Search by area and keyword
gurume search --area 東京 --keyword 寿司
# Search with a precise cuisine filter
gurume search --area 三重 --cuisine すき焼き
# Change sort order and output format
gurume search --area 大阪 --cuisine ラーメン --sort ranking --output json
# List all supported cuisines
gurume list-cuisines
# Start the TUI
gurume tui
# Start the MCP server
gurume mcpCurrent gurume search options:
--area,-a--keyword,-k--cuisine,-c--sort,-s:ranking,review-count,new-open,standard--limit,-n--output,-o:table,json,simple
Notes:
- For natural-language input, use the
gurume-cliagent skill with an AI assistant — it decomposes free-form text into the structured flags above. - Reservation filters, detail fetching, and page selection are available in the Python API and MCP tools, but are not currently exposed as CLI flags.
from gurume import SortType
from gurume import query_restaurants
restaurants = query_restaurants(
area="銀座",
keyword="寿司",
party_size=2,
sort_type=SortType.RANKING,
)
for restaurant in restaurants[:3]:
print(restaurant.name, restaurant.rating, restaurant.url)from gurume import PriceRange
from gurume import RestaurantSearchRequest
from gurume import SortType
request = RestaurantSearchRequest(
area="渋谷",
keyword="焼肉",
reservation_date="20250715",
reservation_time="1900",
party_size=4,
sort_type=SortType.RANKING,
price_range=PriceRange.DINNER_4000_5000,
online_booking_only=True,
has_private_room=True,
)
restaurants = request.search_sync()
print(f"Found {len(restaurants)} restaurants")import asyncio
from gurume import SearchRequest
async def main() -> None:
request = SearchRequest(
area="新宿",
keyword="居酒屋",
max_pages=2,
include_meta=True,
)
response = await request.search()
print(response.status)
print(response.meta.total_count if response.meta else None)
for restaurant in response.restaurants[:5]:
print(restaurant.name, restaurant.review_count)
asyncio.run(main())from gurume import RestaurantDetailRequest
detail = RestaurantDetailRequest(
restaurant_url="https://tabelog.com/tokyo/A1307/A130704/13053564/",
fetch_reviews=True,
fetch_menu=True,
fetch_courses=True,
max_review_pages=2,
).fetch_sync()
print(detail.restaurant.name)
print(len(detail.reviews), len(detail.menu_items), len(detail.courses))from gurume import get_all_genres
from gurume import get_genre_code
print(get_genre_code("すき焼き"))
print(get_all_genres()[:5])Gurume ships a FastMCP server for AI assistants and other MCP-compatible clients.
GitHub development version:
{
"mcpServers": {
"gurume": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/narumiruna/gurume",
"gurume",
"mcp"
]
}
}
}PyPI release:
{
"mcpServers": {
"gurume": {
"command": "uvx",
"args": ["gurume", "mcp"]
}
}
}Local development:
{
"mcpServers": {
"gurume": {
"command": "uv",
"args": [
"run",
"--directory",
"/home/<user>/workspace/gurume",
"gurume",
"mcp"
]
}
}
}-
tabelog_search_restaurantsSearch by area, keyword, or cuisine with structured pagination metadata.Parameters:
area: optional area, prefecture, city, or station namekeyword: optional free-text keyword for restaurant names or general matchingcuisine: optional cuisine name in Japanese for precise genre filteringsort:ranking,review-count,new-open,standardlimit: 1 to 60, default20page: 1-based page number, default1reservation_date:YYYYMMDDreservation_time:HHMMparty_size: positive integer
Returns a structured
RestaurantSearchOutputenvelope with:statusitemsreturned_countlimithas_moremetaapplied_filterswarningserror
-
tabelog_list_cuisinesReturn the supported cuisine list as structured data. -
tabelog_get_restaurant_detailsFetch a restaurant detail page and optionally collect reviews, menu items, and courses.Parameters:
restaurant_url: required Tabelog restaurant URLfetch_reviews: defaulttruefetch_menu: defaulttruefetch_courses: defaulttruemax_review_pages: minimum1, default1
-
tabelog_get_area_suggestionsReturn structured area and station suggestions from Tabelog. -
tabelog_get_keyword_suggestionsReturn structured keyword suggestions for cuisines, restaurant names, and combined terms.
- Validate the area with
tabelog_get_area_suggestionswhen the user input is ambiguous. - Validate cuisines or restaurant names with
tabelog_get_keyword_suggestions. - Call
tabelog_search_restaurantswith normalized values. - Continue with
page + 1whenmeta.has_next_pageis true. - Call
tabelog_get_restaurant_detailsfor shortlisted restaurants.
All MCP tools return structured error data instead of relying on free-form exception text.
Current stable error codes:
invalid_parametersunsupported_cuisineupstream_unavailableinternal_error
When status="error", inspect error.error_code, error.retryable, and error.suggested_action first.
# Run the MCP test suite
uv run pytest -q tests/test_server.py
# Start the server locally (stdio, default)
uv run gurume mcp
# Inspect tools and schemas interactively
npx @modelcontextprotocol/inspector uv run gurume mcpgurume mcp can also run as an HTTP server for clients that speak streamable
HTTP (or SSE):
# Streamable HTTP (recommended; endpoint at http://127.0.0.1:8000/mcp)
uv run gurume mcp --transport streamable-http
# Custom bind address, port, and path
uv run gurume mcp --transport streamable-http --host 0.0.0.0 --port 9001 --path /api/mcp
# Server-Sent Events transport
uv run gurume mcp --transport sse --port 8765 --path /eventsSecurity note: the default bind is 127.0.0.1. Use --host 0.0.0.0 only on
trusted networks; the MCP endpoint has no built-in authentication.
Start the Textual TUI with:
uv run gurume tuiOr:
python -m gurume.tuiThe TUI includes:
- a two-column layout with search results and a detail panel
- area suggestions with
F2 - keyword and cuisine suggestions with
F3 - automatic cuisine detection for direct cuisine-name input
- visible sort controls and keyboard navigation
Detailed TUI documentation lives in docs/TUI_USAGE.md.
This repo ships an agent skill at skills/gurume-cli/ that teaches AI coding assistants (Claude Code, Codex CLI, etc.) when and how to call the gurume CLI for restaurant search on Tabelog.
Install it with skills:
npx skills add narumiruna/gurumeThis pulls skills/gurume-cli/ into your local agent skills directory. After installing, your agent will reach for gurume automatically whenever you ask it to find restaurants in Japan — by area, cuisine, or a vague "where should I eat" prompt.
See the examples/ directory for runnable scripts:
examples/basic_search.py: simple, advanced, and async search examplesexamples/restaurant_detail.py: restaurant detail scraping examplesexamples/cli_example.py: standalone example CLI built on the Python API
- Gurume scrapes Tabelog pages and internal suggestion endpoints. Upstream HTML or API changes may break parsing.
- Tabelog data is primarily Japanese. Even when user input is multilingual, normalized search values and many results are Japanese.
- Natural-language input is no longer parsed inside the CLI/TUI. Use the
gurume-cliagent skill with an AI assistant to translate free-form text into structured flags. - Reservation-related search results reflect Tabelog availability data and may change over time.
- Use the library responsibly and avoid excessive request volume.
This project is intended for educational and research use.
- Respect Tabelog terms of service and robots policies.
- Do not send excessive or abusive traffic.
- Add your own rate limiting and operational safeguards for production use.
MIT License
Contributions are welcome. Please open an issue or submit a pull request.