Skip to main content
Glama
philogicae

Torrent Search MCP Server

by philogicae

Torrent Search MCP/API/WebUI

uv Python PyPI Actions status License: MIT Ask DeepWiki

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

Run it with Docker to bypass common DNS issues

Search directly from the command line

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

Related MCP server: rqbit Torrent Client MCP

Table of Contents

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 (a Web UI POPULAR click passes refresh=true to drop the caches and re-scrape every source); 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.la + 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 env var.

Setup

Prerequisites

  • Python 3.10+ (required for PyPI install). CI and Docker images use Python 3.14.

  • 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:<hash>&dn=<name>; 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.

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:

pip install torrent-search-mcp
  1. Create a .env file in the directory where you'll run the application (optional).

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

python -m torrent_search

For Local Development

This method is for contributors who want to modify the source code. Using uv:

  1. Clone the repository:

git clone https://github.com/philogicae/torrent-search-mcp.git
cd torrent-search-mcp
  1. Install dependencies using uv:

uv sync --frozen
  1. Create your configuration file by copying the example:

cp .env.example .env
  1. Run the MCP server (default: stdio):

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:

./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 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):

git clone https://github.com/philogicae/torrent-search-mcp.git
cd torrent-search-mcp
  1. Create your configuration file by copying the example:

cp .env.example .env
  1. Build and run the containers using Docker Compose:

docker compose up --build -d
  1. Access container logs:

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).

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 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.

# 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

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

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:

# With Python
python -m torrent_search --mode api
# With uv
uv run -m torrent_search --mode api
  • --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. Caching and request coalescing are in-process, so each worker keeps its own cache; use the default single worker unless per-worker caches are acceptable (a shared backend such as Redis would be needed to scale out).

The API server will then be accessible at http://<host>:<port>.

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

  • GET /: Built-in web UI (dark/light) - search, per-site popular tiles, sortable results, source-page links and magnet actions. Telegram sending requires one-time QR pairing when configured.

  • POST /torrent/search: Search for torrents. Query params: query (required), max_items (optional, default 20; uncapped when per_source is set) and per_source (optional, keep up to N results per source, ranked by swarm health).

  • GET /sources: List the available torrent source domains.

  • GET /torrent/popular: Get the most popular torrents. Query params: per_source (optional, default 20) and refresh (optional, default false; true drops the server-side caches and fetches a fresh listing from every source - the Web UI POPULAR button does this on each click).

  • GET /torrent/{torrent_id}: Get the magnet link for a specific torrent by id. Returns the magnet URI as a JSON string.

  • GET /telegram/session: Web UI auth state (enabled, authenticated, public bot handle, prune_magnet_links). Send the session token as Authorization: Bearer.

  • POST /telegram/auth/challenge: Create a one-time 16-character alphanumeric pairing code (rate-limited). Codes expire after ~5 minutes and are shown as a QR + deep link in the pairing popup.

  • GET /telegram/auth/poll?code=: Poll a pairing code; on approval returns the one-time session token for the browser to store.

  • DELETE /telegram/auth/challenge/{code}: Cancel a pending pairing code.

  • POST /telegram/auth/register: Approve a pairing code bound to a Telegram chat_id. Requires Authorization: Bearer $TORRENT_SEARCH_API_KEY.

  • POST /telegram/auth/logout: Revoke the presented session token.

  • POST /forward_telegram: Send torrent info to the Telegram chat bound to the presented session token; server-to-server callers may instead use Authorization: Bearer $TORRENT_SEARCH_API_KEY with the target chat_id query param. JSON body: filename (required), magnet_link (required), optional size, seeders. When PRUNE_MAGNET_LINKS=true the forwarded magnet is pruned; requires TELEGRAM_BOT_TOKEN, otherwise 503.

  • /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(user_intent, query): Search for torrents across all available sources.

    • user_intent: A short description reflecting the user's overall intention (e.g. "latest episode of Sample Show").

    • query: Optimized, lowercase, space-separated keywords (e.g. "sample show s01e05"). Generic/filler/technical terms should be stripped per the tool's docstring.

    • By default magnet links are stripped from the response to save tokens; set INCLUDE_LINKS=true to include them.

    • Magnet round trips: with INCLUDE_LINKS unset, results keep their id but no magnet. After picking the 2-5 torrents worth recommending, call get_torrent(id) once per pick: the server resolves it from its 1-hour torrent cache, or re-runs the search if the entry expired. Do not fetch magnets for every result.

  • popular_torrents(per_source=20): Get the most popular torrents right now from sources with an official top listing (apibay, uindex, 1337x, YTS, nyaa, EZTV) - up to per_source results each, grouped per source and pre-ranked by seeders + leechers.

    • By default magnet links are stripped from the response to save tokens; set INCLUDE_LINKS=true to include them.

  • available_sources(): Get the list of available torrent sources.

  • get_torrent(torrent_id): Get the magnet link for a specific torrent by id (the id returned by search_torrents or popular_torrents).

  • authorize_webapp(code, chat_id): Approve a Web UI pairing code bound to your Telegram chat id (the code shown in the browser pairing gate). Requires TORRENT_SEARCH_API_KEY and TORRENT_SEARCH_API_URL.

  • forward_torrent(filename, magnet_link, chat_id, size=None, seeders=None): Forward a torrent (filename + magnet) to your Telegram chat through the REST API (magnet pruned when PRUNE_MAGNET_LINKS=true). Requires TORRENT_SEARCH_API_KEY and TORRENT_SEARCH_API_URL; rate-limited per chat (20/min).

  • torrent_webapp(): Present the web UI URL (WEBUI_URL) and its pairing-based access system.

Example with Devin

Configuration:

{
  "mcpServers": {
    ...
    # with stdio (only requires uv)
    "torrent-search-mcp": {
      "command": "uvx",
      "args": [ "torrent-search-mcp" ]
    },
    # with streamable-http transport (Docker compose: MCP on port 8001; standalone server: 8000)
    "torrent-search-mcp": {
      "serverUrl": "http://127.0.0.1:8001/mcp"
    },
    # with sse transport (legacy; requires running server)
    "torrent-search-mcp": {
      "serverUrl": "http://127.0.0.1:8001/sse"
    },
    ...
  }
}

Changelog

See 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 file for details.

Available Tools

7 tools
authorize_webappAuthorize WebappA

Authorize a browser on the Torrent Search webapp via its pairing code.

The code comes from an user interaction on the webapp: they click "Open in Telegram", scan the QR code, or copy the prompt message, which sends "Authorize for Torrent Search" to you. Take the code from that message and call this tool with it and the user's Telegram chat id. Codes are single-use and expire after 5 minutes. After approval the user MUST go back to the webapp: the browser polls and completes the authentication there (it shows "Access granted" and unlocks the app permanently).

NameRequiredDescriptionDefault
codeYesPairing code shown in the webapp 'Telegram Access' gate.
chat_idYesThe owner's Telegram chat id the webapp access is bound to.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full behavioral burden. It discloses important non-obvious traits: codes are single-use, expire after 5 minutes, and authentication is only completed in the browser once the user returns to the webapp. This is strong transparency for an authorization tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The single-sentence purpose statement is front-loaded, followed by a compact workflow explanation. No filler or redundant content; every sentence adds relevant operational detail, though the length is slightly more than minimal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with a full schema and output schema, the description covers the complete invocation flow: source of the code, required inputs, single-use/expiry constraint, and the required post-call user action. Minor details like error handling for invalid/expired codes are absent but acceptable given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds meaningful context beyond the schema by explaining where the code comes from, its exact message format, and that it must be paired with the user's Telegram chat id. This helps an agent correctly extract and pass parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'Authorize a browser on the Torrent Search webapp via its pairing code.' This clearly identifies the tool's action and distinguishes it from sibling tools like search, get, and forward, which have different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It thoroughly explains when to use the tool: when a user sends an 'Authorize <CODE> for Torrent Search' message, with the code and chat id as inputs. It doesn't explicitly list alternative tools to use instead, but no siblings fulfill this same role, so exclusion is not necessary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

available_sourcesAvailable SourcesB

Get the list of available torrent sources.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It only says 'Get the list', implying a read operation, but gives no detail on side effects, permissions, caching, or failure modes. There is no contradiction, but the disclosure is too thin.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no wasted words. It is concise, though it is also very sparse – perhaps too sparse to fully convey the tool's role.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple zero-parameter interface and the presence of an output schema, the description is mostly adequate. However, it omits any context about what a 'torrent source' is, why a user would call this, or how it fits into the workflow (e.g., before searching).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so no parameter semantics are needed. Schema description coverage is trivially 100% and the baseline for a no-parameter tool is 4, which applies here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Get the list of available torrent sources'. It clearly indicates a retrieval operation unlike the sibling search, popular, or forward tools, though it doesn't explicitly contrast itself with them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus its siblings. It doesn't mention that it could be a prerequisite for search_torrents or that it only lists supported sources. No alternatives or exclusions are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

forward_torrentForward TorrentA

Send a torrent (filename + magnet) to the user's Telegram chat.

The forward goes through the Torrent Search REST API, which owns the Telegram bot token; when PRUNE_MAGNET_LINKS is enabled the magnet is pruned to 'magnet:?xt=urn:btih:HASH&dn=' before sending. Requires TORRENT_SEARCH_API_KEY (same value as the API server) and TORRENT_SEARCH_API_URL. Forwards are rate-limited per chat (20/min).

NameRequiredDescriptionDefault
sizeNoOptional human-readable size (e.g. '1.2 GiB').
chat_idYesThe owner's Telegram chat id the torrent is sent to.
seedersNoOptional seeder count.
filenameYesExact torrent filename shown in the search results.
magnet_linkYesMagnet link of the torrent (from get_torrent, or from a search run with INCLUDE_LINKS=true), as the bare magnet: drop the untrusted-data notice and tag lines, they are not part of the link and would break the forward.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and does it well: it discloses the REST API dependency, bot-token ownership, required TORRENT_SEARCH_API_KEY and TORRENT_SEARCH_API_URL, the per-chat rate limit of 20/min, and — importantly — that PRUNE_MAGNET_LINKS may rewrite the magnet payload before sending. It omits failure behavior (e.g. what happens when the rate limit is hit) and whether forwards are persisted or deduplicated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The action is front-loaded in the first sentence, followed by tightly packed operational detail (API dependency, pruning, credentials, rate limit). No sentence is filler, though the environment-variable clause is slightly dense and could be trimmed for an agent-facing reader.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the description covers the prerequisites, the rate limit, and the payload-mutation behavior an agent must know before calling. It is nearly complete for a 5-parameter side-effecting tool, with only error/retry semantics left unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all five parameters including the optional size and seeders fields and the bare-magnet requirement. The description adds only the 'filename + magnet' pairing, which the schema already implies; baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'Send a torrent (filename + magnet) to the user's Telegram chat' — which immediately tells an agent this is a delivery/forwarding action rather than a lookup. It does not explicitly contrast itself with siblings like get_torrent, search_torrents, or torrent_webapp, so the boundary is inferred rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied through the mention that the magnet comes 'from get_torrent, or from a search run with INCLUDE_LINKS=true', which routes the agent to the right sibling for input gathering. However there is no explicit when-to-use vs when-not statement (e.g. forwarding vs opening the webapp), so the guidance is indirect.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_torrentGet TorrentA

Get the magnet link for a specific torrent by id.

The result is wrapped in the untrusted-data fence: the magnet is the fenced value itself, the notice and tag lines are not part of the link.

NameRequiredDescriptionDefault
torrent_idYesTorrent ID returned by a previous search_torrents or popular_torrents call.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it delivers a genuinely non-obvious behavioral detail: the magnet is wrapped in an untrusted-data fence, and the fenced value itself is the link while notice/tag lines are not. That directly affects how an agent consumes the result. It stops short of disclosing auth needs, error behavior for missing ids, or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the purpose, followed by the essential result-parsing rule. No filler and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter getter with an output schema present, the description covers purpose and the non-obvious fencing semantics of the return value. It omits what happens when the id does not resolve, which is a minor but real gap for a lookup tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single parameter already documents that the id is 'returned by a previous search_torrents or popular_torrents call.' The description repeats only 'by id' and adds no format or validation detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Get the magnet link for a specific torrent by id.' That is concrete and distinct from search_torrents and popular_torrents. It does not explicitly name a sibling to differentiate against, which keeps it below a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'by id' and the schema note that the id comes from a previous search_torrents or popular_torrents call imply the use case (you already have an id). There is no explicit when/when-not guidance or comparison against forward_torrent or torrent_webapp, so guidance is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_torrentsSearch TorrentsA

Perform an advanced torrent search across multiple providers.

Result Analysis & Ranking:

  1. Quality: Prefer 1080p or 4k, over 720p.

  2. Efficiency: Prefer h265/HEVC for better quality/size ratio.

  3. Health: Maximize seeders + leechers.

  4. Size: Prefer smaller files within the same quality bracket.

  5. Language: Ultimately, if multiple equivalent options are available, choose the one with more languages.

Response Requirements:

  • Recommend the top 3-5 results maximum.

  • For each recommendation, include: Filename, Size, Seeds/Leechs, Date, Source, and a 1-sentence "Why this?" reason.

  • If results are poor, irrelevant or too diverse, suggest specific keywords to improve the search.

NameRequiredDescriptionDefault
queryYesOptimized search keywords, lowercase and space-separated. Strip generic terms (movie, torrent, download), filler words (the, a, of) and technical tags (1080p, h265, bluray) unless explicitly requested. TV shows: 'name sXXeYY' for episodes, 'name sXX' for seasons. Add 'multi' only if a multi-language version is requested.
user_intentYesUser's overall intention (e.g. 'latest episode of Sample Show').

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It transparently explains the ranking criteria (quality, efficiency, health, size, language) and the response format (top 3-5 results with specific fields and 'Why this?' reasons), plus the fallback of suggesting keywords. This is substantial and goes beyond basic operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with headers and bullet points, making it scannable, but it's fairly long with detailed ranking and response requirements. While each section is informative, it could be more concise; the ranking criteria and response format are somewhat verbose, though they do add context. It's not overly redundant but is longer than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of the tool (multi-provider search, ranking, response formatting) and the presence of an output schema, the description covers the essential behavior, query construction, ranking logic, and response requirements, including a fallback for poor results. It doesn't mention auth or limitations, but for a search tool with an output schema, it's sufficiently complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already describes both parameters with 100% coverage, so the baseline is 3. The description adds significant value by detailing how to construct the query (strip generic terms, TV show format, 'multi' flag), which is not in the schema. This enriches the meaning of the query parameter beyond its type/description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs an advanced torrent search across multiple providers, which is a specific action and resource. However, it doesn't explicitly differentiate itself from siblings like popular_torrents or get_torrent beyond calling itself 'advanced' and mentioning 'multiple providers', so it's clear but not fully distinguishing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no explicit guidance on when to use this tool versus alternatives. It gives detailed ranking and response instructions, but doesn't say when to prefer this over popular_torrents or other siblings, nor does it mention exclusions or conditions. Usage is only implied by the search nature.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

torrent_webappTorrent WebappA

Present the Torrent Search webapp and its Telegram pairing access system.

Returns the webapp URL and how to get authorized by you. Tell the user to open the URL: on first visit the site shows a pairing dialog with a QR code and buttons ("Open in Telegram", "t.me" fallback, "Copy Prompt"). Ask the user to scan the QR code, click "Open in Telegram", or copy the prompt message and send it to you in the Telegram chat. That message ("Authorize for Torrent Search") carries the code; when it arrives, extract it and call authorize_webapp with it and the user's Telegram chat id. Codes expire after 5 minutes.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It transparently explains the pairing dialog, the buttons, the code expiration (5 minutes), and instructs the agent to call authorize_webapp with the extracted code and chat id. This covers all relevant behaviors and side effects (the tool returns a URL and guides a user interaction). The only minor gap is not explicitly stating that no data is modified, but it's implied by the presentation nature.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is moderately long but every sentence contributes to the user interaction flow—it explains the URL, the pairing dialog, the actions, the code extraction, and the expiry. It is well-structured, starting with the purpose and then detailing steps. It could be slightly more compact by merging some sentences, but the detail is necessary for this interactive tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (an interactive pairing process with user involvement), the description is complete. It covers the output (webapp URL), the steps the agent must take, the exact message format, the expiry, and the call to authorize_webapp. An output schema exists (though not shown), so return-value details are presumably covered there. Nothing essential is missing for an agent to correctly invoke and follow through.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so schema coverage is trivially 100%. The description correctly does not need to explain parameters, and it adds no parameter-related details. Baseline for zero parameters is 4, and the description's focus on behavior is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: to present the Torrent Search webapp and its Telegram pairing system, returning the webapp URL and the authorization procedure. It distinguishes itself from sibling tools like search_torrents or authorize_webapp by focusing on the initial presentation and pairing flow, not on searching or authorizing directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit step-by-step usage instructions: tell the user to open the URL, guide them through the QR code/Telegram options, extract the code from their message, and call authorize_webapp. It clearly defines when to use this tool (to initiate pairing) and the follow-up action, though it doesn't explicitly contrast with alternatives like 'use search_torrents when searching'—but the flow is self-contained and unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev4.6.1
    • Changedforward_torrent5 fields changed
      • changedInput schema / properties / magnet_link / description
        Previous value: -"Magnet link of the torrent (from get_torrent, or from a search run with INCLUDE_LINKS=true)."New value: +"Magnet link of the torrent (from get_torrent, or from a search run with INCLUDE_LINKS=true), as the bare magnet: drop the untrusted-data notice and tag lines, they are not part of the link and would break the forward."
      • changedInput schema / properties / seeders / anyOf
        Previous value: -[
        -  {
        -    "anyOf": [
        -      {
        -        "type": "integer"
        -      },
        -      {
        -        "type": "null"
        -      }
        -    ],
        -    "description": "Optional seeder count."
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / seeders / description
        Added value: +"Optional seeder count."
      • changedInput schema / properties / size / anyOf
        Previous value: -[
        -  {
        -    "anyOf": [
        -      {
        -        "type": "string"
        -      },
        -      {
        -        "type": "null"
        -      }
        -    ],
        -    "description": "Optional human-readable size (e.g. '1.2 GiB')."
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / size / description
        Added value: +"Optional human-readable size (e.g. '1.2 GiB')."
  2. 2 tool updatesv4.5.0
    • Addedforward_torrent
    • Changedsearch_torrents1 field changed
      • changedInput schema / properties / user_intent / description
        Previous value: -"User's overall intention (e.g. 'latest episode of Breaking Bad')."New value: +"User's overall intention (e.g. 'latest episode of Sample Show')."
  3. 6 tool updatesv4.3.3
    • Addedauthorize_webapp
    • Addedavailable_sources
    • Changedget_torrent1 field changed
      • addedInput schema / properties / torrent_id / description
        Added value: +"Torrent ID returned by a previous search_torrents or popular_torrents call."
    • Addedpopular_torrents
    • Changedsearch_torrents2 fields changed
      • addedInput schema / properties / query / description
        Added value: +"Optimized search keywords, lowercase and space-separated. Strip generic terms (movie, torrent, download), filler words (the, a, of) and technical tags (1080p, h265, bluray) unless explicitly requested. TV shows: 'name sXXeYY' for episodes, 'name sXX' for seasons. Add 'multi' only if a multi-language version is requested."
      • addedInput schema / properties / user_intent / description
        Added value: +"User's overall intention (e.g. 'latest episode of Breaking Bad')."
    • Addedtorrent_webapp
  4. 4 tool updatesv2.4.0
    • Addedget_torrent
    • Removedget_ygg_magnet_link
    • Removedget_ygg_torrent_details
    • Changedsearch_torrents7 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • removedInput schema / properties / max_items
        Removed value: -{
        -  "default": 10,
        -  "title": "Max Items",
        -  "type": "integer"
        -}
      • removedInput schema / properties / query / title
        Removed value: -"Query"
      • removedInput schema / properties / sources
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "items": {
        -        "type": "string"
        -      },
        -      "type": "array"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Sources"
        -}
      • addedInput schema / properties / user_intent
        Added value: +{
        +  "type": "string"
        +}
      • changedInput schema / required
        Previous value: -[
        -  "query"
        -]New value: +[
        +  "user_intent",
        +  "query"
        +]
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "result": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "result"
        +  ],
        +  "type": "object",
        +  "x-fastmcp-wrap-result": true
        +}
  5. 3 tool updatesv1.0.0
    • First observedget_ygg_magnet_link
    • First observedget_ygg_torrent_details
    • First observedsearch_torrents

TDQS

A3.8/5.0

Scored across 7 tools

Disambiguation4/5

Most tools have clearly distinct purposes: search, popular listings, source listing, magnet retrieval, forwarding, and webapp authorization. The main potential confusion is between torrent_webapp and authorize_webapp, though the descriptions distinguish presenting the webapp from performing the actual authorization.

Naming Consistency4/5

All tool names use snake_case, which is consistent and readable. However, the naming patterns vary between verb_noun (get_torrent, forward_torrent), adjective_noun (available_sources, popular_torrents), and noun_noun (torrent_webapp), so it is not a uniform verb_noun convention.

Tool Count5/5

Seven tools is a well-scoped set for torrent search plus Telegram forwarding and webapp authorization. Each tool appears to earn its place, with no obvious redundant operations.

Completeness4/5

The set covers the core workflows: discovering sources, searching, browsing popular torrents, retrieving a magnet link, forwarding to Telegram, and authorizing the webapp. Minor gaps might include richer torrent detail retrieval or pagination/filtering by source, but agents can work around them.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers