Skip to main content
Glama
README.md
# ParkAlert MCP

An MCP server that exposes Disney ride status and wait times as on-demand tools,
backed by the [ThemeParks.wiki](https://api.themeparks.wiki/) API.

This is the pull-based sibling of [ParkAlert](https://github.com/austin5374/parkalert),
a PWA that polls the same API on a timer and pushes a notification through ntfy.sh
when a ride goes down or comes back up. ParkAlert answers "tell me when something
changes." This server answers "what is the situation right now, because I just asked."
The API client is ported from ParkAlert's `server/themeparks.js`; the polling loop,
the transition detection, the trip codes, and the notification fan-out are all
deliberately left behind.

## Tools

| Tool | Arguments | Answers |
| --- | --- | --- |
| `get_ride_status` | `park`, `ride` | Is this ride operating, down, or closed right now? |
| `get_wait_time` | `park`, `ride` | How long is the standby line right now? |

Both tools accept a park by name, alias, or ThemeParks.wiki entity ID
("Magic Kingdom", "dhs", "epcot"), and a ride by however a person would say it.
Partial and near-miss names such as "space mountain" or "tron" are matched, and an
ambiguous name comes back with the candidates it could have meant.

Supported parks: Magic Kingdom, EPCOT, Hollywood Studios, Animal Kingdom,
Disneyland (CA), California Adventure. Add more by appending to `PARKS` in
`src/parkalert_mcp/parks.py`.

## Setup

Requires Python 3.10 or newer, which is the `mcp` SDK's floor. Note that the
system `python3` on macOS may well be older than that, so name the interpreter
explicitly rather than relying on whatever `python3` resolves to.

```bash
python3.12 -m venv .venv
.venv/bin/pip install -e .
```

`requirements-lock.txt` records the exact versions this server is known to work
against, captured from a working environment. It exists because the dependency
that matters here is a moving target: `mcp` 2.0 renamed `FastMCP` to `MCPServer`,
so a rebuild that quietly resolved to a different major version would fail at
import with no hint as to why. To reproduce the known-good environment instead of
resolving fresh versions:

```bash
python3.12 -m venv .venv
.venv/bin/pip install -r requirements-lock.txt
.venv/bin/pip install --no-deps -e .
```

Regenerate the lockfile after changing dependencies:

```bash
.venv/bin/pip freeze --exclude-editable > requirements-lock.txt
```

The `--exclude-editable` flag is load-bearing. A plain `pip freeze` writes this
project back out as a `-e git+https://...@<commit>` line, which would send a
future rebuild off to clone the repository rather than installing the checkout
already in hand.

## Tests

```bash
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
```

The suite covers the two functions that decide what a caller's words mean:
`find_attraction` in `themeparks.py` and `resolve_park` in `parks.py`. Both run
offline, against a capture of real Magic Kingdom and EPCOT attraction data frozen
in `tests/conftest.py`. The tests therefore describe the matching rules and their
precedence, not today's ride list, and a ride opening or closing upstream will not
turn them red.

One test does reach the network. It fetches `/live` for all six park entity IDs
and asserts that each still returns attractions, which is precisely the failure
the offline tests cannot see. It is marked `network` and deselected by default,
so it runs only when asked for:

```bash
.venv/bin/python -m pytest -m network
```

## Running it

The server speaks stdio, so it is launched by its client rather than run as a
long-lived service. To exercise it by hand:

```bash
.venv/bin/python -m parkalert_mcp.server
```

For an interactive tool browser, the MCP Inspector works against the same command:

```bash
npx @modelcontextprotocol/inspector .venv/bin/python -m parkalert_mcp.server
```

## Claude Desktop

Add the server to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "parkalert": {
      "command": "/Users/austin/parkalert-mcp/.venv/bin/python",
      "args": ["-m", "parkalert_mcp.server"]
    }
  }
}
```

The absolute path to the venv's Python matters: Claude Desktop does not run through
a login shell, so a bare `python` would not resolve to this environment. Restart
Claude Desktop after editing, then look for the tools under the connectors icon.

## Credits

Built by Austin Vodrazka with Claude.

TDQS

A4.4/5.0

Scored across 2 tools

Disambiguation3/5

The two tools accept the same park/ride arguments and both return status plus wait time, so an agent could reasonably pick either for a wait or status question. However, the descriptions clearly steer status checks to get_ride_status and wait-time questions to get_wait_time, reducing confusion.

Naming Consistency5/5

Both tools follow the same get_<resource>_<metric> pattern: get_ride_status and get_wait_time. The naming is predictable and mirrors the two core queries perfectly.

Tool Count3/5

Two tools is on the thin side for a general-purpose MCP server, but the scope is intentionally narrow: live Disney ride status and standby wait times. The count feels minimal but not unreasonable for that focused domain.

Completeness4/5

The core domain is covered: agents can check whether a ride is operating, down, or closed, and get standby wait minutes with status context to interpret Nones. Minor gaps exist, such as no way to list all rides in a park, but the main user intents are served.

Maintenance

ActivityMaintained
ResponsivenessNo issues