# Torrent Search Mcp

> MCP/API/WebUI to find torrents programmatically

- **Type:** MCP server
- **Install:** `agentstack add mcp-philogicae-torrent-search-mcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [philogicae](https://agentstack.voostack.com/s/philogicae)
- **Installs:** 0
- **Category:** [Search](https://agentstack.voostack.com/c/search)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [philogicae](https://github.com/philogicae)
- **Source:** https://github.com/philogicae/torrent-search-mcp
- **Website:** https://deepwiki.com/philogicae/torrent-search-mcp

## Install

```sh
agentstack add mcp-philogicae-torrent-search-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Torrent Search MCP/API/WebUI

[](https://docs.astral.sh/uv/getting-started/installation/)
[](https://www.python.org/downloads/)
[](https://badge.fury.io/py/torrent-search-mcp)
[](https://github.com/philogicae/torrent-search-mcp/actions)
[](https://opensource.org/licenses/MIT)
[](https://deepwiki.com/philogicae/torrent-search-mcp)

This repository provides a Python API/WebUI and an MCP (Model Context Protocol) server to find torrents programmatically on **ThePirateBay**, **1337x**, **Nyaa**, **YTS**, **EZTV**, **FitGirl**, **SubsPlease** and **UIndex**. It allows for easy integration into other applications or services.

  

## Quickstart

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

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

> [Search directly from the command line](#as-cli)

```bash
uvx torrent-search-mcp --mode cli "sample show"

# MCP server over stdio (default)
uvx torrent-search-mcp --mode stdio

# MCP server over streamable HTTP (port 8000, endpoint /mcp)
uvx torrent-search-mcp --mode http

# MCP server over SSE (port 8000, endpoint /sse, legacy)
uvx torrent-search-mcp --mode sse

# Standalone API server (port 8000)
uvx torrent-search-mcp --mode api
```

## Table of Contents

- [Features](#features)
- [Supported Sources](#supported-sources)
- [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 CLI](#as-cli)
  - [As Python Wrapper](#as-python-wrapper)
  - [As MCP Server](#as-mcp-server)
  - [As API Server](#as-api-server)
  - [Via MCP Clients](#via-mcp-clients)
    - [Example with Devin](#example-with-devin)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [License](#license)

## Features

- API wrapper for **ThePirateBay**, **1337x**, **Nyaa**, **YTS**, **EZTV**, **FitGirl**, **SubsPlease** and **UIndex**.
- MCP server interface (FastMCP 4) serving the `2026-07-28` protocol revision over `stdio` or streamable HTTP (`http`), with automatic negotiation of older handshake revisions and legacy transport aliases (`streamable-http`, `sse`).
- API server interface for alternative HTTP access (e.g., for direct API calls or testing).
- CLI mode for quick one-off searches directly from the terminal.
- `popular_torrents` cached for 2 minutes for Web UI delivery; searches are never cached (only identical concurrent requests are coalesced) so new results appear immediately.
- In-memory 1-hour, 5000-entry torrent cache used only to resolve magnet links via `get_torrent` without re-scraping.
- Magnet links are always stored internally; MCP hides them unless `INCLUDE_LINKS=true`.
- Configurable source filtering via environment variables.
- Telegram-gated web UI: one-time QR/deep-link pairing, forward-to-Telegram popup and (optional) server-side forwarding.
- Tools:
  - Search for torrents across all available sources.
  - Get the most popular torrents per source (apibay, uindex, 1337x, YTS, nyaa, EZTV).
  - Get the magnet link for a specific torrent by id.
  - List available sources.
  - Present the web UI and its Telegram pairing access, approve pairing codes, and forward torrents to Telegram chats.

## Supported Sources

| Source       | Scraping domain        | Fetch method          |
| ------------ | ---------------------- | --------------------- |
| ThePirateBay | `apibay.org`           | JSON API              |
| 1337x        | `1337x.to` + mirrors   | HTML search/top pages |
| Nyaa         | `nyaa.si`              | RSS + HTML top page   |
| YTS          | `yts.mx` + mirrors     | JSON API              |
| EZTV         | `eztvx.to`             | JSON API              |
| FitGirl      | `fitgirl-repacks.site` | RSS                   |
| SubsPlease   | `subsplease.org`       | JSON API              |
| UIndex       | `uindex.org`           | HTML top list         |

The API exposes public display domains where applicable: `apibay.org` is shown as `thepiratebay.org`, and `yts.mx` as `yts.vg`. Results may include a validated HTTP(S) `page_url` linking back to their source page.

> **Note on UIndex:** the site exposes no programmatic search endpoint (its search path is protected by a browser challenge), so queries are matched client-side against its live top list - which conveniently carries magnet links inline.

Sources can be excluded individually via the [`EXCLUDE_SOURCES`](#configuration-optional) env var.

## Setup

### Prerequisites

- Python 3.10+ (required for PyPI install). CI and Docker images use Python 3.14.
- [`uv`](https://github.com/astral-sh/uv) (for local development).
- Docker and Docker Compose (for Docker setup).

### Configuration (Optional)

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.

| Variable                 | Default                    | Description                                                                                                                                                                                                                                      |
| ------------------------ | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `INCLUDE_LINKS`          | `false`                    | When `true`, include magnet links in the MCP `search_torrents` / `popular_torrents` results. Left off by default to greatly reduce token usage.                                                                                                  |
| `EXCLUDE_SOURCES`        | _(none)_                   | Comma-separated list of sources to exclude from results (e.g. `nyaa.si,1337x.to`).                                                                                                                                                               |
| `TORRENT_SEARCH_API_URL` | _(none)_                   | MCP only: base URL of a running Torrent Search REST API - tools proxy it instead of scraping locally. Unset = standalone.                                                                                                                        |
| `TELEGRAM_BOT_HANDLE`    | _(none)_                   | Telegram bot handle used by the Web UI torrent action. Unset = the web UI runs without the pairing gate and Telegram features stay hidden.                                                                                                       |
| `TORRENT_SEARCH_API_KEY` | _(none)_                   | Secret required to approve Web UI pairing codes (register endpoint + `authorize_webapp` MCP tool). Must match between API and MCP servers. Unset = pairing disabled (no gate).                                                                   |
| `TELEGRAM_BOT_TOKEN`     | _(none)_                   | Bot token enabling server-side sending via `POST /forward_telegram` (non-agent mode). Unset = that endpoint replies 503 unless agent mode is configured; the Web UI forward popup still works through Telegram draft deep links.                 |
| `AGENT_RELAY_URL`        | _(none)_                   | Agent relay mode (with `AGENT_RELAY_TOKEN`, required): forward becomes a Confirm/Cancel dialog POSTing `{chat_id, sender, notice, prompt}` to the agent's HTTP relay instead of the Bot API (bots never receive bot-authored Telegram messages). |
| `AGENT_RELAY_TOKEN`      | _(none)_                   | Agent relay mode: shared secret sent as the `X-Relay-Token` header; must match the agent's `AGENT_RELAY_TOKEN`.                                                                                                                                  |
| `TELEGRAM_AGENT_NAME`    | _(none)_                   | Agent relay mode: `sender` name passed to the relay (spoofed as the chat identity downstream).                                                                                                                                                   |
| `TELEGRAM_MSG_FORWARD`   | _(none)_                   | Agent relay mode: `notice` echoed into the chat by the agent before it processes the prompt.                                                                                                                                                     |
| `PRUNE_MAGNET_LINKS`     | `false`                    | When `true`, magnets sent over every Telegram path (forward popup draft + `/forward_telegram`) are pruned to `magnet:?xt=urn:btih:&dn=`; copy/magnet buttons keep originals.                                                         |
| `TELEGRAM_AUTH_FILE`     | `./authorized_tokens.json` | Persistence file for authorized session tokens (SHA-256 hashes only); shared between API and MCP processes via mtime-based reload.                                                                                                               |
| `WEBUI_URL`              | _(none)_                   | MCP only: public URL of the web UI; enables the `torrent_webapp` tool that presents the app and its pairing flow.                                                                                                                                |

### 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
```

2.  Create a `.env` file in the directory where you'll run the application (optional).

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 --frozen
```

3.  Create your configuration file by copying the example:

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

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

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

The repo also ships a `dev.sh` helper that locks/syncs deps, formats, lints, type-checks (`ty`) and runs the test suite with coverage:

```bash
./dev.sh
```

#### For Docker

This method uses Docker Compose to run **two containers**: the REST API + web UI, and an MCP server that proxies the API (no local scraping).

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

| Container            | Mode   | Host port | Endpoints                                                                                  |
| -------------------- | ------ | --------- | ------------------------------------------------------------------------------------------ |
| `torrent-search-api` | `api`  | `8000`    | `/` (web UI), `/torrent/*`, `/sources`, `/docs`                                            |
| `torrent-search-mcp` | `http` | `8001`    | `/mcp` (MCP over streamable HTTP, `TORRENT_SEARCH_API_URL=http://torrent-search-api:8000`) |

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:

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

3.  Build and run the containers using Docker Compose:

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

4.  Access container logs:

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

## Usage

The package exposes a single entry point, `torrent-search-mcp` (installed by `pip`/`uvx`), equivalent to `python -m torrent_search`. It supports the following `--mode` values:

| Mode              | Endpoint | Description                                                                                                                                  |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `cli`             | -        | Run a single search query and print results to stdout.                                                                                       |
| `stdio`           | -        | MCP server over stdio (default).                                                                                                             |
| `http`            | `/mcp`   | MCP server using streamable HTTP. Serves MCP protocol revision `2026-07-28` (sessionless) and negotiates older revisions for legacy clients. |
| `streamable-http` | `/mcp`   | Alias of `http` (legacy fastmcp transport name).                                                                                             |
| `sse`             | `/sse`   | MCP server using Server-Sent Events. Legacy HTTP transport (deprecated by the MCP spec in favor of `http`).                                  |
| `api`             | `/`      | Standalone API HTTP server (see [As API Server](#as-api-server)).                                                                            |

The server is built on FastMCP 4 (MCP SDK v2). Clients supporting the `2026-07-28` revision negotiate it automatically (stateless requests, `server/discover`, no session IDs); older clients fall back to the previous handshake era against the same deployment.

MCP modes (`stdio`, `http`, `streamable-http`, `sse`) run **standalone** by default (tools scrape locally). Set [`TORRENT_SEARCH_API_URL`](#configuration-optional) to switch to **API mode**: the tools proxy a running Torrent Search REST API instead.

Common flags (for `http`, `streamable-http`, `sse` and `api` modes): `--host` (default `0.0.0.0`), `--port` (default `8000`), `--reload`, `--workers` (API only).

### As CLI

Run a one-off search directly from the terminal. Prints each result as `id (seeders|leechers|downloads) - filename`, then fetches the magnet/torrent for the top hit.

```bash
# Using the installed entry point
torrent-search-mcp --mode cli "sample show"

# Or via uvx without installing
uvx torrent-search-mcp --mode cli "sample show"

# Or from source
uv run -m torrent_search --mode cli "sample show"
```

### As Python Wrapper

```python
from torrent_search import torrent_search_api

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

`search_torrents` is async and accepts an optional `max_items` (default `20`). `popular_torrents(per_source=20)` returns the current most popular torrents from sources with a top listing - up to `per_source` results per source (pass `per_source=None` for everything), merged and ranked by seeders + leechers. Each `Torrent` exposes `id`, `filename`, `category`, `size`, `seeders`, `leechers`, `downloads`, `date`, `source`, `uploader`, and, when available, `magnet_link` and a validated HTTP(S) `page_url`. Pass a torrent's `id` to `get_torrent()` to retrieve its magnet link.

### As MCP Server

```python
from torrent_search import torrent_search_mcp

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

### As API Server

This project also includes a API 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 API Server:**

```bash
# With Python
python -

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [philogicae](https://github.com/philogicae)
- **Source:** [philogicae/torrent-search-mcp](https://github.com/philogicae/torrent-search-mcp)
- **License:** MIT
- **Homepage:** https://deepwiki.com/philogicae/torrent-search-mcp

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-philogicae-torrent-search-mcp
- Seller: https://agentstack.voostack.com/s/philogicae
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
