Skip to main content
Glama
patw
by patw
README.md10.3 kB
# MongoDB Movie Database FastMCP Tools This project provides a Python script that exposes a set of powerful tools for querying and analyzing a MongoDB movie database (specifically the `sample_mflix` dataset) using the `fastmcp` library. These tools are designed to be easily integrated with large language models (LLMs), AI agents, or any other system requiring structured, programmatic access to movie data. ## Table of Contents * [Features](#features) * [Prerequisites](#prerequisites) * [MongoDB Setup](#mongodb-setup) * [Installation](#installation) * [Usage](#usage) * [FastMCP Tools](#fastmcp-tools) * [`find_movies`](#find_movies) * [`count_movies`](#count_movies) * [`get_average_rating`](#get_average_rating) * [Contributing](#contributing) * [License](#license) ## Features * **Comprehensive Movie Search:** Find movies by title, genre, actors, directors, writers, year, or various rating thresholds. * **Flexible Data Retrieval:** Specify fields to return (`projection_fields`) and control sorting (`sort_by`, `sort_order_asc`). * **Movie Counting:** Quickly count movies matching specific criteria. * **Average Rating Calculation:** Compute average IMDb, Metacritic, or Rotten Tomatoes ratings for filtered movie sets. * **LLM-Friendly:** Designed with `fastmcp` to create a robust, self-documenting API easily consumable by LLMs. Includes special handling for stringified list arguments, addressing common LLM output formats. * **Robust MongoDB Integration:** Utilizes `pymongo` for efficient and reliable database operations. ## Prerequisites Before running this project, ensure you have the following: * **Python 3.7+**: [Download Python](https://www.python.org/downloads/) * **MongoDB Instance**: A running MongoDB instance (local or cloud-hosted like MongoDB Atlas). * **`sample_mflix` Dataset**: The `sample_mflix` database and its `movies` collection must be loaded into your MongoDB instance. ### Optionally * Claude Desktop ``` { "mcpServers": { "Movie Database": { "command": "uv", "args": [ "run", "--with", "fastmcp, pymongo", "fastmcp", "run", "<path to>/movie-mcp/movie-mcp.py", "<mongo connection string URI>" ] } } } ``` ## MongoDB Setup This application connects to the `sample_mflix` database and specifically the `movies` collection. **If you're using MongoDB Atlas:** 1. Log in to your [MongoDB Atlas account](https://cloud.mongodb.com/). 2. Navigate to your cluster. 3. Go to the "..." (usually `Data` or `Load Sample Data`) tab. 4. Click "Load Sample Dataset" and select `sample_mflix`. This will automatically import the necessary data. **If you're using a local MongoDB instance:** You can download the `sample_mflix` dataset from MongoDB's official resources (e.g., as part of the MongoDB University course materials or directly from their sample data repositories) and import it using `mongoimport`. ## Installation 1. **Clone the repository:** ```bash git clone https://github.com/patw/movie-mcp.git cd movie-mcp ``` 2. **Install dependencies:** ```bash pip install -r requirements.txt ``` ## Usage The script expects the MongoDB connection URI as a command-line argument. 1. **Run the script:** ```bash python movie_tools.py "mongodb://localhost:27017/" ``` Or, if using a MongoDB Atlas connection string: ```bash python movie_tools.py "mongodb+srv://user:pass@clusterdomain/?retryWrites=true&w=majority" ``` Replace `user`, `pass` and `clusterdomain` with your actual MongoDB Atlas credentials and cluster details. 2. **FastMCP Server:** Once running, the script will start a `fastmcp` server. This server exposes the defined tools (e.g., `find_movies`, `count_movies`) over a local HTTP endpoint (by default `http://127.0.0.1:8000/tools`). You can then interact with these tools programmatically, typically from an LLM agent or another Python script. Example of how an LLM or another program might call these tools (conceptually): ```python # This is pseudo-code representing how an LLM agent might interact # In a real scenario, you'd use a client library for fastmcp or direct HTTP requests. # Example: Find movies by Bill Murray tool_call = { "tool_name": "find_movies", "args": { "actors": ["Bill Murray"], "limit": 5, "projection_fields": ["title", "year", "imdb.rating"] } } # result = make_tool_call(tool_call) # print(result) # Example: Count romantic comedies from the 90s tool_call = { "tool_name": "count_movies", "args": { "genres": ["Comedy", "Romance"], "start_year": 1990, "end_year": 1999 } } # result = make_tool_call(tool_call) # print(result) ``` ## FastMCP Tools This section details the functions exposed as tools by `fastmcp`. ### `find_movies` Finds movies based on a variety of criteria, with options for sorting and limiting results. ```python def find_movies( title: Optional[str] = None, genres: Optional[Union[List[str], str]] = None, actors: Optional[Union[List[str], str]] = None, directors: Optional[Union[List[str], str]] = None, writers: Optional[Union[List[str], str]] = None, year: Optional[int] = None, start_year: Optional[int] = None, end_year: Optional[int] = None, min_imdb_rating: Optional[float] = None, min_metacritic_rating: Optional[int] = None, min_tomatoes_viewer_rating: Optional[float] = None, min_tomatoes_critic_rating: Optional[float] = None, rated_mpaa: Optional[str] = None, sort_by: Optional[str] = "imdb.rating", sort_order_asc: bool = False, limit: int = 10, projection_fields: Optional[List[str]] = None ) -> List[Dict[str, Any]]: ``` **Args:** * `title` (str, optional): Movie title (case-insensitive partial match). * `genres` (List[str] or str, optional): List of genres; movie must match all specified genres. If a single string is passed (e.g., "Comedy"), it's treated as a list of one. * `actors` (List[str] or str, optional): List of actor names; movie must feature all specified actors (case-insensitive partial match for each name within the cast list). If a single string is passed, it's treated as a list of one. * `directors` (List[str] or str, optional): List of director names; movie must be directed by all specified directors (case-insensitive partial match for each name). If a single string is passed, it's treated as a list of one. * `writers` (List[str] or str, optional): List of writer names; movie must include all specified writers (case-insensitive partial match for each name). If a single string is passed, it's treated as a list of one. * `year` (int, optional): Exact release year. * `start_year` (int, optional): Start of a release year range (inclusive). * `end_year` (int, optional): End of a release year range (inclusive). * `min_imdb_rating` (float, optional): Minimum IMDb rating (e.g., 7.5). * `min_metacritic_rating` (int, optional): Minimum Metacritic score (e.g., 70). * `min_tomatoes_viewer_rating` (float, optional): Minimum Rotten Tomatoes viewer rating (e.g., 3.5). * `min_tomatoes_critic_rating` (float, optional): Minimum Rotten Tomatoes critic rating (e.g., 7.0). * `rated_mpaa` (str, optional): MPAA rating (e.g., "R", "PG-13"). Case-insensitive exact match. * `sort_by` (str, optional): Field to sort results by. Can be a MongoDB path (e.g., "imdb.rating", "year", "title") or a short key ("imdb", "metacritic", "tomatoes_viewer", "tomatoes_critic", "imdb_votes", "tomatoes_viewer_num_reviews", "tomatoes_critic_num_reviews"). Defaults to 'imdb.rating'. * `sort_order_asc` (bool, optional): Sort order. `False` for descending (default, e.g., highest rated first), `True` for ascending (e.g., lowest rated first). * `limit` (int, optional): Maximum number of results to return. Defaults to 10. Use `0` for no limit. * `projection_fields` (List[str], optional): Specific fields to return for each movie (e.g., `["title", "year"]`). Defaults to a standard set (`title`, `year`, `plot`, `imdb.rating`, `genres`). **Returns:** * `List[Dict[str, Any]]`: A list of movie documents (or specified fields). Returns an empty list if no movies match the criteria or an error occurs. ### `count_movies` Counts movies based on the specified criteria. ```python def count_movies( title: Optional[str] = None, genres: Optional[Union[List[str], str]] = None, actors: Optional[Union[List[str], str]] = None, directors: Optional[Union[List[str], str]] = None, writers: Optional[Union[List[str], str]] = None, year: Optional[int] = None, start_year: Optional[int] = None, end_year: Optional[int] = None, min_imdb_rating: Optional[float] = None, min_metacritic_rating: Optional[int] = None, min_tomatoes_viewer_rating: Optional[float] = None, min_tomatoes_critic_rating: Optional[float] = None, rated_mpaa: Optional[str] = None ) -> int: ``` **Args:** (Same as the filtering arguments for the `find_movies` tool) **Returns:** * `int`: The number of movies matching the criteria. Returns `0` if an error occurs. ### `get_average_rating` Calculates the average rating for movies matching the criteria, for a specific rating type. ```python def get_average_rating( rating_field_key: str, genres: Optional[Union[List[str], str]] = None, actors: Optional[Union[List[str], str]] = None, directors: Optional[Union[List[str], str]] = None, writers: Optional[Union[List[str], str]] = None, year: Optional[int] = None, start_year: Optional[int] = None, end_year: Optional[int] = None ) -> Optional[Dict[str, Any]]: ``` **Args:** * `rating_field_key` (str): The key for the rating source (e.g., "imdb", "metacritic", "tomatoes_viewer", "tomatoes_critic"). * (Other filtering arguments are similar to those in `find_movies`/`count_movies`, excluding `title`, `min_ratings`, and `rated_mpaa` as they are less common for broad average calculations). **Returns:** * `Optional[Dict[str, Any]]`: A dictionary containing `'average_rating'` (float, rounded to 2 decimal places) and `'movie_count'` (int). Returns `None` if the `rating_field_key` is invalid, or a dict with `None` average_rating and `0` count if no movies match or an error occurs. ## Contributing Contributions are welcome! If you have suggestions for improvements, new features, or bug fixes, please open an issue or submit a pull request. ## License This project is open-sourced under the MIT License. See the `LICENSE` file for more details.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/patw/movie-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server