Skip to main content
Glama
danielsteman

Filmladder MCP Server

by danielsteman
README.md
# Filmladder MCP Server

A Model Context Protocol (MCP) server that provides movie listings and recommendations for Amsterdam cinemas by scraping [filmladder.nl](https://www.filmladder.nl/amsterdam/bioscopen).

## Features

- **List Movies**: Get all movies playing in Amsterdam cinemas, optionally filtered by date
- **Get Showtimes**: Find all showtimes for a specific movie (with fuzzy title matching)
- **Cinema Movies**: List all movies playing at a specific cinema
- **Recommendations**: Get movie recommendations based on rating, preferred showtimes, cinemas, and date

## Requirements

- Python 3.11 or higher
- Poetry for dependency management

## Installation

1. Clone the repository:

   ```bash
   git clone <repository-url>
   cd filmladder-mcp
   ```

2. Install dependencies using Poetry:

   ```bash
   poetry install
   ```

3. Install pre-commit hooks (optional but recommended):

   ```bash
   poetry run pre-commit install
   ```

4. Copy `.env.example` to `.env` and adjust configuration if needed:
   ```bash
   cp .env.example .env
   ```

## Usage

### Running the MCP Server

The server uses stdio transport and can be run directly:

```bash
poetry run python -m src.server
```

### Connecting to Cursor IDE

To use this MCP server in Cursor:

1. **Project-specific configuration** (recommended):

   - The project includes a `.cursor/mcp.json` file with the server configuration
   - Cursor should automatically detect it when you open this project

2. **Manual configuration**:

   - Open Cursor Settings (gear icon)
   - Go to **Tools & Integrations** → **MCP Tools**
   - Click **Add Custom MCP** or edit `mcp.json`
   - Add the following configuration:

   ```json
   {
     "mcpServers": {
       "filmladder-mcp": {
         "command": "poetry",
         "args": ["run", "python", "-m", "src.server"],
         "cwd": "/path/to/filmladder-mcp"
       }
     }
   }
   ```

   **Important**: Replace `/path/to/filmladder-mcp` with the actual path to this project directory.

3. **Verify connection**:
   - After saving, Cursor should show "filmladder-mcp" in the MCP Tools section
   - You can test it by asking Cursor: "What movies are playing in Amsterdam today?"

### Using the MCP Tools in Cursor

Once connected, you can use the tools in Cursor's chat:

- **List movies**: "What movies are playing in Amsterdam?"
- **Get showtimes**: "When is Nuremberg playing?"
- **Cinema movies**: "What movies are playing at Pathé Tuschinski?"
- **Recommendations**: "Recommend me a movie with rating above 7.0 for tonight"

### MCP Tools

The server exposes the following tools:

#### `list_movies`

List all movies playing in Amsterdam cinemas.

**Parameters:**

- `date` (optional): Date filter in YYYY-MM-DD format

**Example:**

```json
{
  "date": "2025-01-15"
}
```

#### `get_showtimes`

Get all showtimes for a specific movie (fuzzy matching on title).

**Parameters:**

- `movie_title` (required): Title of the movie

**Example:**

```json
{
  "movie_title": "Nuremberg"
}
```

#### `list_cinema_movies`

List all movies playing at a specific cinema.

**Parameters:**

- `cinema_name` (required): Name of the cinema

**Example:**

```json
{
  "cinema_name": "Pathé Tuschinski"
}
```

#### `recommend_movies`

Recommend movies based on various criteria.

**Parameters:**

- `min_rating` (optional): Minimum rating threshold (default: 0.0)
- `preferred_times` (optional): Array of preferred showtimes in HH:MM format
- `preferred_cinemas` (optional): Array of preferred cinema names
- `date` (optional): Target date for recommendations in YYYY-MM-DD format

**Example:**

```json
{
  "min_rating": 7.0,
  "preferred_times": ["20:00", "21:00"],
  "preferred_cinemas": ["Pathé Tuschinski", "EYE"],
  "date": "2025-01-15"
}
```

## Testing

### Unit Tests

Run the test suite:

```bash
poetry run pytest tests/
```

Run with verbose output:

```bash
poetry run pytest tests/ -v
```

### Quick Server Test

Test that the server initializes correctly:

```bash
poetry run python test_server.py
```

This will verify that:

- The server can be imported
- Tools are registered correctly
- Basic functionality works

### Testing with MCP Inspector

The recommended way to test the full MCP server is using the [MCP Inspector](https://www.stainless.com/mcp/how-to-test-mcp-servers):

1. Install MCP Inspector (if not already installed):

   ```bash
   npm install -g @modelcontextprotocol/inspector
   ```

2. Run the inspector:

   ```bash
   npx @modelcontextprotocol/inspector
   ```

3. Configure the inspector to use your server:

   - Server command: `poetry run python -m src.server`
   - Transport: stdio

4. The inspector will provide an interactive interface to test all tools.

### Manual Testing

You can also test the server manually by running it and sending JSON-RPC messages via stdin:

```bash
poetry run python -m src.server
```

Then send initialization and tool call requests in JSON-RPC format.

## Development

### Code Quality

This project uses:

- **ruff** for linting and import sorting
- **black** for code formatting
- **mypy** for type checking
- **pre-commit** hooks to ensure code quality
- **pytest** for testing

Run linting and formatting:

```bash
poetry run ruff check src/
poetry run black src/
poetry run mypy src/
```

Run tests:

```bash
poetry run pytest tests/
```

### Project Structure

```
filmladder-mcp/
├── src/
│   ├── __init__.py
│   ├── server.py          # MCP server entry point
│   ├── scraper.py         # Web scraping logic
│   ├── models.py          # Pydantic data models
│   ├── config.py          # Pydantic-settings configuration
│   └── recommender.py     # Recommendation logic
├── pyproject.toml         # Poetry dependencies and project config
├── .pre-commit-config.yaml # Pre-commit hooks configuration
├── .cursorrules           # Cursor IDE rules
├── README.md             # This file
└── .env.example          # Example environment variables
```

### Type Annotations

All code must use type annotations. The project follows Python 3.11+ type hinting conventions:

- Use `list[T]` instead of `List[T]`
- Use `str | None` instead of `Optional[str]`
- All functions, methods, and variables must be typed

### Pydantic Models

All data structures use Pydantic BaseModel for validation and serialization. Configuration uses `pydantic-settings` for environment variable support.

## Error Handling

The server handles:

- Network errors (HTTP timeouts, connection failures)
- Parsing errors (HTML structure changes)
- Invalid input parameters

Errors are raised as exceptions that the MCP framework will handle appropriately.

## License

[Add your license here]

## Contributing

[Add contributing guidelines here]