# Torrent Search MCP Server & API

[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://docs.astral.sh/uv/getting-started/installation/)
[![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)
[![PyPI](https://badge.fury.io/py/torrent-search-mcp.svg?cache-control=no-cache)](https://badge.fury.io/py/torrent-search-mcp)
[![Actions status](https://github.com/philogicae/torrent-search-mcp/actions/workflows/python-package-ci.yml/badge.svg?cache-control=no-cache)](https://github.com/philogicae/torrent-search-mcp/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/philogicae/torrent-search-mcp)

This repository provides a Python API and an MCP (Model Context Protocol) server to find torrents programmatically on **ThePirateBay**, **Nyaa**, **1337x**, **YggTorrent (now [ygg.gratis](https://ygg.gratis))** and **La Cale**. It allows for easy integration into other applications or services.

> **Fork note:** this is a private fork of [philogicae/torrent-search-mcp](https://github.com/philogicae/torrent-search-mcp) that adds 1337x.to support via a sidecar scraper (`torrent_search/wrapper/leetx.py`). The 1337x integration uses BeautifulSoup rather than the regex pipeline used for TPB/Nyaa, to keep the new code self-contained and the fork easy to rebase.

<a href="https://glama.ai/mcp/servers/@philogicae/torrent-search-mcp">
  <img width="380" height="200" src="https://glama.ai/mcp/servers/@philogicae/torrent-search-mcp/badge?cache-control=no-cache" alt="Torrent Search MCP server" />
</a>

## Quickstart

> [How to use it with MCP Clients](#via-mcp-clients)

> [Run it with Docker to bypass common DNS issues](#for-docker)

## Table of Contents

- [Features](#features)
- [Setup](#setup)
  - [Prerequisites](#prerequisites)
  - [Configuration](#configuration-optional)
  - [Installation](#installation)
    - [Install from PyPI (Recommended)](#install-from-pypi-recommended)
    - [For Local Development](#for-local-development)
    - [For Docker](#for-docker)
- [Usage](#usage)
  - [As Python Wrapper](#as-python-wrapper)
  - [As MCP Server](#as-mcp-server)
  - [As FastAPI Server](#as-fastapi-server)
  - [Via MCP Clients](#via-mcp-clients)
    - [Example with Windsurf](#example-with-windsurf)
- [Contributing](#contributing)
- [Changelog](#changelog)
- [License](#license)

## Features

- API wrapper for **ThePirateBay**, **Nyaa**, **1337x**, **YTS** (movies, JSON API), **EZTV** (TV, scrape), **TorrentGalaxy** (scrape), **Solid Torrents** (JSON API), **BTDigg** (DHT meta-search, scrape), **YggTorrent (now [ygg.gratis](https://ygg.gratis))** and **La Cale**.
- MCP server interface for standardized communication (stdio, sse, streamable-http)
- FastAPI server interface for alternative HTTP access (e.g., for direct API calls or testing)
- Tools:
  - Search for torrents across all available sources
  - Get magnet link or torrent file for a specific torrent by id

## Setup

### Prerequisites

- Python 3.10+ (required for PyPI install).
- [`uv`](https://github.com/astral-sh/uv) (for local development)
- Docker and Docker Compose (for Docker setup)
- Passkey for LaCale (Optional). Create your apikey on https://la-cale.space/settings/api-keys
- **Network access caveat (new sidecars):** YTS, TorrentGalaxy, Solid Torrents, EZTV, and BTDigg are routinely blocked by German ISPs and other regulated networks (DNS sinkholing to OpenDNS's 146.112.61.106, Cloudflare 403, HTTP 429). The sidecar code gracefully no-ops with a printed error when this happens.
  - **Recommended fix:** route every sidecar through an upstream proxy by setting `SIDECAR_PROXY` (the YTS/EZTV/TGx/Solid/BTDigg sidecars all honor it via a shared `httpx` client factory). Examples:
    - `SIDECAR_PROXY=socks5://user:pass@10.9.0.7:1080` (SOCKS5 — needs `httpx[socks]`, included)
    - `SIDECAR_PROXY=http://proxy.internal:3128` (HTTP CONNECT)
  - **Alternative:** `EXCLUDE_SOURCES=yts.mx,torrentgalaxy.to,solidtorrents.net,eztvx.to,btdig.com` to suppress them on filtered networks.
- **1337x only:** a running [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) instance. 1337x is fronted by Cloudflare's JS challenge; FlareSolverr resolves it. `compose.yaml` includes a `flaresolverr` service. For local dev (most common: `uv run` MCP against containerized FlareSolverr), the default `FLARESOLVERR_URL=http://localhost:8191/v1` works as-is. If you also run the MCP in Docker, note that the existing services use `network_mode: bridge` (legacy bridge, no inter-container DNS) — give the two containers a shared user-defined network if you need them to talk by service name. **Eager-magnet cost:** each search issues 1 + N FlareSolverr fetches (search page + N detail pages for magnets); steady-state ~20s for `max_items=10`. To disable 1337x entirely, set `EXCLUDE_SOURCES=1337x.to` or `LEETX_ENABLE=0` (Docker only).

### Configuration (Optional)

This application requires credentials if you want to interact with La Cale.

1.  **La Cale**: Find your API key on the La Cale website.
2.  **Set Environment Variables**: The application reads configuration from environment variables. The recommended way to set them is by creating a `.env` file in your project's root directory. The application will load it automatically. See `.env.example` for all available options.

### Installation

Choose one of the following installation methods.

#### Install from PyPI (Recommended)

This method is best for using the package as a library or running the server without modifying the code.

1.  Install the package from PyPI:

```bash
pip install torrent-search-mcp
crawl4ai-setup # For crawl4ai/playwright
playwright install --with-deps chromium # If previous command fails
```

2.  Create a `.env` file in the directory where you'll run the application and add your credentials (optional):

```env
LA_CALE_API_KEY=your_api_key_here
```

3.  Run the MCP server (default: stdio):

```bash
python -m torrent_search
```

#### For Local Development

This method is for contributors who want to modify the source code.
Using [`uv`](https://github.com/astral-sh/uv):

1.  Clone the repository:

```bash
git clone https://github.com/philogicae/torrent-search-mcp.git
cd torrent-search-mcp
```

2.  Install dependencies using `uv`:

```bash
uv sync --locked
uvx playwright install --with-deps chromium
```

3.  Create your configuration file by copying the example and add your credentials (optional):

```bash
cp .env.example .env
```

4.  Run the MCP server (default: stdio):

```bash
uv run -m torrent_search
```

#### For Docker

This method uses Docker to run the server in a container.

compose.yaml is configured to bypass DNS issues (using [quad9](https://quad9.net/) DNS).

1.  Clone the repository (if you haven't already):

```bash
git clone https://github.com/philogicae/torrent-search-mcp.git
cd torrent-search-mcp
```

2.  Create your configuration file by copying the example and modify it (optional):

```bash
cp .env.example .env
```

3.  Build and run the container using Docker Compose (default port: 8000):

```bash
docker compose up --build -d
```

4.  Access container logs:

```bash
docker logs torrent-search-mcp -f
```

## Usage

### As Python Wrapper

```python
from torrent_search import torrent_search_api

results = torrent_search_api.search_torrents('...')
for torrent in results:
    print(f"{torrent.filename} | {torrent.size} | {torrent.seeders} SE | {torrent.leechers} LE | {torrent.date} | {torrent.source}")
```

### As MCP Server

```python
from torrent_search import torrent_search_mcp

torrent_search_mcp.run(transport="sse")
```

### As FastAPI Server

This project also includes a FastAPI server as an alternative way to interact with the library via a standard HTTP API. This can be useful for direct API calls, integration with other web services, or for testing purposes.

**Running the FastAPI Server:**

```bash
# With Python
python -m torrent_search --mode fastapi
# With uv
uv run -m torrent_search --mode fastapi
```

- `--host <host>`: Default: `0.0.0.0`.
- `--port <port>`: Default: `8000`.
- `--reload`: Enables auto-reloading when code changes (useful for development).
- `--workers <workers>`: Default: `1`.

The FastAPI server will then be accessible at `http://<host>:<port>`

**Available Endpoints:**
The FastAPI server exposes similar functionalities to the MCP server. Key endpoints include:

- `/`: A simple health check endpoint. Returns `{"status": "ok"}`.
- `/torrent/search`: Search for torrents (POST request with `query` and optional `max_items` parameters).
- `/torrent/{torrent_id}`: Get magnet link or torrent file for a specific torrent by id.
- `/docs`: Interactive API documentation (Swagger UI).
- `/redoc`: Alternative API documentation (ReDoc).

Environment variables are configured the same way as for the MCP server (via an `.env` file in the project root).

### Via MCP Clients

Usable with any MCP-compatible client. Available tools:

- `search_torrents`: Search for torrents across all available sources (ThePirateBay, Nyaa, La Cale).
- `get_torrent`: Get the magnet link or torrent file for a specific torrent by id.

Available resources:

- `data://torrent_sources`: Get the list of available torrent sources.

#### Example with Windsurf

Configuration:

```json
{
  "mcpServers": {
    ...
    # with stdio (only requires uv)
    "torrent-search-mcp": {
      "command": "uvx",
      "args": [ "torrent-search-mcp" ]
    },
    # with sse transport (requires installation)
    "torrent-search-mcp": {
      "serverUrl": "http://127.0.0.1:8000/sse"
    },
    # with streamable-http transport (requires installation)
    "torrent-search-mcp": {
      "serverUrl": "http://127.0.0.1:8000/mcp" # not yet supported by every client
    },
    ...
  }
}
```

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for a history of changes to this project.

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
