sf-mm-mcp

sf-mm-mcp

Enables searching movies and TV shows, finding magnet links, and starting downloads on put.io via natural language from MCP clients like Claude.

Category
Visit Server

README

<img src="https://raw.githubusercontent.com/githendrik/sf-mm-mcp/main/assets/logo-256.png" alt="" width="96" align="left">

sf-mm-mcp

An MCP server that exposes moviemagnet.site (movies) and showfeed.site (TV shows) to LLM clients, with put.io as the download backend.

Search a title, find magnet links ranked by seeders, and start the download on put.io — all from inside Claude Desktop, Claude Code, opencode, or any other MCP client.

npx sf-mm-mcp login    # one-time put.io sign-in
npx sf-mm-mcp          # start the server on stdio

Setup

1. Add the server to your MCP client

The put.io app id (9525) is built in, so there is nothing to configure for a default install.

Claude Desktop (claude_desktop_config.json), Claude Code (.mcp.json), and opencode (opencode.json) all use the same shape:

{
  "mcpServers": {
    "sf-mm": {
      "command": "npx",
      "args": ["-y", "sf-mm-mcp"]
    }
  }
}

opencode

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "sfmm": {
      "type": "local",
      "command": ["npx", "-y", "sf-mm-mcp"],
      "enabled": true
    }
  }
}

opencode prefixes tool names with the server name, so the tools appear as sfmm_movies_search, sfmm_putio_login, and so on. Verify the connection with opencode mcp list.

Note that opencode mcp auth does not apply here. That command drives OAuth for remote MCP servers via dynamic client registration; this is a local stdio server that manages its own put.io credential. Use the sign-in below instead.

See docs/clients.md for Cursor, VS Code, Windsurf, Zed, Cline and others.

2. Sign in

Either run npx sf-mm-mcp login in a terminal, or ask your assistant to call the putio_login tool and follow the instructions it returns.

putio_login is non-blocking by design, so the in-chat flow works: the tool returns a code immediately, you enter it at put.io/link, and putio_auth_status confirms. The token is stored per-machine, so signing in once covers every MCP client on that machine.

Authentication

The default is put.io's OOB (out-of-band) device flow: the server requests a short code, you enter it at https://put.io/link, and the server polls until it is linked.

This is the default rather than the more familiar redirect flow for a specific reason: an npx-distributed package cannot hold a client secret. Anything baked into the tarball is readable by everyone who installs it. The OOB flow needs no secret and no loopback listener, so it also works over SSH and inside containers.

If you control the environment and prefer the redirect flow, set:

SF_MM_AUTH_FLOW=loopback
PUTIO_CLIENT_SECRET=...          # supply it yourself; never commit it
PUTIO_REDIRECT_URI=http://127.0.0.1:41830/callback

The redirect URI must match one registered on your put.io app. state is generated per handshake and verified on the callback.

Where the token is stored

In order of preference:

  1. PUTIO_TOKEN environment variable, if set (nothing is persisted).
  2. OS keychain — macOS Keychain via security, Linux via secret-tool.
  3. A 0600 file at ~/.config/sf-mm-mcp/token.json.

npx sf-mm-mcp status reports which backend is in use. npx sf-mm-mcp logout clears it.

Tools

Discovery — no sign-in required

Tool Purpose
movies_search Find movies by title, returns IMDb ids
movies_get Full details for one movie
movies_popular Most-viewed movies on moviemagnet.site
shows_search Find TV shows by title
shows_get Show details plus episode list, optionally one season
shows_popular Most-viewed shows on showfeed.site

Torrents — sign-in required

Tool Purpose
movies_find_torrents Magnets for a movie, filterable by resolution and seeders
shows_find_torrents Magnets for a show, filterable by season, episode, resolution

Results are normalised to {title, magnet, sizeHuman, seeders, resolution, season, episode, ageDays} and sorted by seeder count.

put.io — sign-in required

Tool Purpose
putio_add_transfer Start a download from a magnet or URL
putio_list_transfers List transfers with progress
putio_get_transfer Poll a single transfer
putio_cancel_transfers Cancel or remove transfers
putio_clean_transfers Clear completed transfer entries
putio_account Username and disk usage
putio_list_files Browse files and folders
favorites_list / favorites_update Read and edit the favorites list

Favorites are stored in the put.io account config under the same favorites key the two websites use, so the list stays in sync across all three.

Auth

putio_login, putio_auth_status, putio_logout.

putio_login returns instructions immediately rather than blocking — waiting for a human to finish a browser flow would hold the tool call open for minutes and most clients time out first. Poll putio_auth_status to confirm.

Configuration

All optional.

Variable Default Purpose
PUTIO_CLIENT_ID 9525 put.io OAuth app id (public); override to use your own app
PUTIO_TOKEN — Use a token directly, skipping sign-in
SF_MM_AUTH_FLOW oob oob or loopback
PUTIO_CLIENT_SECRET — Only for loopback
PUTIO_REDIRECT_URI http://127.0.0.1:41830/callback Only for loopback
MOVIEMAGNET_BASE_URL https://moviemagnet.site Point at a dev instance
SHOWFEED_BASE_URL https://showfeed.site Point at a dev instance
PUTIO_API_BASE_URL https://api.put.io/v2
SF_MM_CONFIRM_TRANSFERS false Require confirm=true on putio_add_transfer
SF_MM_TORRENT_CACHE_TTL 900 Torrent result cache, seconds
SF_MM_METADATA_CACHE_TTL 3600 Metadata cache, seconds
SF_MM_TOKEN_STORE auto auto/keychain/file/none; none disables persistence
SF_MM_LOG_LEVEL info debug/info/warn/error/silent

Caching and rate limits

Both websites validate the put.io token on every /api/torrent request, and that endpoint fans out to torrent indexers. An LLM will call these far more eagerly than a human clicking through a web page, so this server:

  • caches torrent results (15 min) and metadata (1 hour) in process,
  • de-duplicates concurrent identical requests,
  • caches token-validation results for 10 minutes rather than revalidating per call,
  • honours put.io's 429 plus X-RateLimit-Reset headers with backoff,
  • never retries a write, so a transfer cannot be silently created twice.

Development

npm install
npm run build
npm run typecheck
npm test           # boots the server, asserts tool surface; no network
npm run smoke      # exercises the live public endpoints over MCP stdio

npm test is network-free on purpose, so CI does not go red because a torrent indexer is having a bad day. It runs with SF_MM_TOKEN_STORE=none so it cannot accidentally pick up a developer's real token and skip the auth-gating checks.

Releasing

npm version patch && git push --follow-tags

Publishing runs from GitHub Actions on a version tag. There is no npm token anywhere: the workflow authenticates with npm via OIDC trusted publishing, which also generates a provenance attestation automatically.

npm version patch     # or minor / major - commits and tags
git push --follow-tags

.github/workflows/publish.yml then refuses to continue unless:

  • the tag matches package.json version exactly,
  • that version is not already on npm,
  • typecheck, build and the tool-surface test all pass,
  • no .env file made it into the tarball.

To rehearse without publishing, run the workflow manually from the Actions tab with dry-run left checked. Full detail in docs/releasing.md.

Documentation

docs/architecture.md Design decisions and why the alternatives lost
docs/auth.md Credential model; why there is no client secret
docs/upstream-apis.md The two sites' API surface and its quirks
docs/clients.md Configuration for every common MCP client
docs/releasing.md Release procedure and CI guards

Agents should start at AGENTS.md.

Point at local dev servers with MOVIEMAGNET_BASE_URL=http://localhost:5173.

Notes on the upstream APIs

Neither site publishes a schema, so the shapes in src/schemas.ts were derived by reading the SvelteKit route handlers and probing the live endpoints. Two things worth knowing:

  • Both sites expect the put.io token in a bare Authorization header with no Bearer prefix. This client matches that.
  • Neither site has a "create transfer" endpoint — the web apps do it client-side. So transfers, account info, and favorites go directly to api.put.io.

Validation failures are logged rather than swallowed, so upstream schema drift shows up as a warning on stderr instead of a silent "no results found".

A bug this client used to work around

Both sites once returned 500 on the first request for any given title, because torrentService.js destructured the Jackett response as const { instance, data: results } — declaring a new block-scoped results that shadowed the outer one, leaving it undefined on every cache miss. It hid well: the shadowed value was still written to Redis, so a retry hit the cache and succeeded. Titles with zero indexer results were never cached and so failed permanently.

Fixed and deployed in both apps (showfeed-app@6640310, moviemagnet-app@77b22fe), along with queryMultipleServices, which only ever called resolve and therefore hung forever if every indexer failed.

The 5xx retry in this client predates those fixes. It is kept because indexers still fail transiently, but it is no longer masking a deterministic upstream failure. Full write-up in docs/upstream-apis.md.

Credits

Logo icons from pepicons by CyCraft, licensed CC BY 4.0. See assets/README.md.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured