@cyanheads/tmdb-mcp-server
v0.1.1
Published
Search movies, TV, and people on The Movie Database (TMDB) — credits, ratings, trailers, images, recommendations, and region-aware streaming availability via MCP. STDIO or Streamable HTTP.
Downloads
317
Maintainers
Readme
Tools
Eight tools organized search-before-detail — tmdb_search_titles resolves a name to an integer id, the get_* tools fetch full records, and tmdb_discover_titles / tmdb_get_trending / tmdb_get_watch_providers cover filtered browsing and streaming availability. TMDB keys on integer ids, not titles, so search comes first.
| Tool | Description |
|:---|:---|
| tmdb_search_titles | Search movies, TV, and people by name. The required first step — resolves a name to the integer id the detail tools consume. |
| tmdb_get_movie | Full movie detail in one call — synopsis, runtime, genres, US certification, budget/revenue, cast, crew, trailers, recommendations, keywords, external ids. |
| tmdb_get_show | Full TV show detail — overview, air dates, status, season/episode counts, creators, networks, season summaries, cast, trailers, content rating. |
| tmdb_get_season | Episode list for one season — names, air dates, runtimes, vote averages, stills, per-episode guest stars, plus the season's regular cast. |
| tmdb_get_person | Person detail and full filmography — biography, vital dates, the combined_credits cast/crew lists, and cross-platform external ids. |
| tmdb_discover_titles | Filtered, sorted discovery across movies or TV — the power-query: genre, date/vote ranges, vote-count floor, cast/crew/network, watch providers, runtime, sort. |
| tmdb_get_trending | Trending movies, TV, or people for the day or week. |
| tmdb_get_watch_providers | Region-scoped streaming availability (JustWatch) — flatrate/rent/buy/ads/free provider lists plus the TMDB link. A region code is required. |
All list and detail responses resolve image *_path fields to full https://image.tmdb.org/t/p/… URLs and resolve genre_ids[] to genre names. Every tool carries the TMDB attribution in its output enrichment.
tmdb_search_titles
Resolve a movie, show, or person name to ranked results with integer ids.
multimode (default) mixes movies, shows, and people, each result tagged withmedia_type;movie/tv/personrestrict to one type and enable type-specific ranking- Optional
yearfilter (movie/tv modes),languageoverride,include_adulttoggle, andpagefor paging past the first 20 - Each result carries
id,media_type, title/name,release_year,overview,vote_average, resolvedgenre_names, and the relevant poster/profile URL - An empty result set is a valid answer, returned with recovery guidance — not an error
tmdb_get_movie
Fetch full movie detail by TMDB id in a single request.
- Folds credits, videos, recommendations, similar, keywords, external ids, and release dates into one call via
append_to_response— trim theappendarray to shrink the payload (e.g.["credits"]for cast only) - US theatrical certification extracted from the
release_datesnamespace; top-billed cast and key crew (Director/Writer/Screenplay/Producer); YouTube trailers with watch URLs - Does not include streaming availability — that is region-specific; use
tmdb_get_watch_providers
tmdb_get_show
Fetch full TV show detail by series id — the series mirror of tmdb_get_movie.
- Same
append_to_responseset, withcontent_ratings(US TV rating) in place ofrelease_dates - Adds season summaries, creators, networks, and the last/next episode to air
- Pass a
season_numberfromseasons[]totmdb_get_seasonfor the episode list
tmdb_get_season
Fetch the episode list for one season of a show — bridges the show-level summary and per-episode detail.
- Per-episode names, air dates, runtimes, vote averages, still URLs, and guest stars (embedded per episode)
- Plus the season's regular recurring cast (distinct from per-episode guest stars)
series_idis echoed from the input — the TMDB season endpoint does not return it. Season 0 is "Specials"
tmdb_get_person
Fetch person detail and the full combined filmography.
- Biography, birth/death dates, place of birth, known-for department, aliases, gender label
combined_creditssplit intocast_creditsandcrew_credits, recency-ordered (most recent first) and capped to a display size — the pre-cap totals are reported and truncation is disclosed in the enrichment- IMDb id plus the extended cross-platform id set (Wikidata, social handles) for chaining to other servers
tmdb_discover_titles
The power-query — filtered, sorted discovery across movies or TV.
- Filter by
with_genres/without_genres, exactyearor arelease_date_gte/ltewindow,vote_averagerange,vote_count_gtefloor,with_cast/with_crew(movie),with_networks(tv),with_watch_providers+watch_region,with_original_language, andruntimerange - Sort by popularity, revenue, vote average, vote count, or release date. Pair
vote_average.descwithvote_count_gte(~100–1000) so a 10.0-from-3-votes title does not dominate with_cast/with_creware movie-only andwith_networksis tv-only on TMDB; the tool accepts them for bothmedia_typevalues and no-ops the inapplicable ones with a noticewith_watch_providersrequires awatch_region— streaming availability is region-specific. Omitting the region returns a typedregion_requirederror
tmdb_get_watch_providers
Find where a movie or TV title streams in one region.
- Returns flatrate (subscription), rent, buy, ads (ad-supported free), and free provider lists with logo URLs, plus the TMDB JustWatch-backed
link— the supported path to actual deep links - A
watch_region(ISO 3166-1 alpha-2) is required: availability is region-specific and there is no global answer; the response always carries a region caveat - An empty result for a region is a valid "not available to stream here" answer, not an error
- Provider ids in the result feed back into
tmdb_discover_titleswith_watch_providers
Resources
| Type | Name | Description |
|:---|:---|:---|
| Resource | tmdb://movie/{movie_id} | Movie detail by id, as injectable context — the same enriched record as tmdb_get_movie. |
| Resource | tmdb://tv/{series_id} | Show detail by id — the same enriched record as tmdb_get_show. |
| Resource | tmdb://person/{person_id} | Person detail and filmography by id — the same record as tmdb_get_person. |
All resource data is also reachable via tools — the three resources are convenience wrappers over the detail service methods, so tool-only clients lose nothing. Search, discovery, trending, and seasons are query paths or intermediate records, not addressable entities, so they have no resources. There are no prompts: this is a data/lookup server with no recurring multi-step interaction template.
Features
Built on @cyanheads/mcp-ts-core:
- Declarative tool and resource definitions — single file per primitive, framework handles registration and validation
- Unified error handling — handlers throw, framework catches, classifies, and formats
- Typed error contracts — every tool declares its failure reasons with recovery guidance for the agent
- Pluggable auth:
none,jwt,oauth - Swappable storage backends:
in-memory,filesystem,Supabase,Cloudflare KV/R2/D1 - Structured logging with optional OpenTelemetry tracing
- STDIO and Streamable HTTP transports — runs locally or on Cloudflare Workers from the same codebase
TMDB-specific:
- Single typed client for the TMDB v3 REST API, authenticated with a v4 Read Access Token over
Authorization: Bearer - Image
*_pathfields resolved to fullhttps://image.tmdb.org/t/p/{size}{path}URLs — null paths omit the field rather than emitting a broken URL genre_ids[]resolved to genre names from per-media_typemaps cached at startup, so list results carry readable genres without an extra call- Detail tools collapse credits, videos, recommendations, similar, keywords, and external ids into one HTTP call via
append_to_response - Region-aware streaming availability backed by JustWatch — region is always an explicit input, never assumed
Agent-friendly output:
- TMDB attribution on every response — surfaced in
enrichment.attributionso it reaches both thestructuredContentandcontent[]client surfaces - Provenance and pagination on list responses — total-result counts, page/total-pages, and an effective-filter notice so agents can reason about what was actually queried
- Empty results and empty provider regions return normally with recovery guidance, not as errors — "no titles matched" and "not streamable here" are real answers an agent must act on
- Region and truncation caveats are explicit — watch-provider results always state the region; capped filmographies disclose the pre-cap totals
Getting started
A TMDB API Read Access Token is required. Create a free TMDB account, then copy the API Read Access Token (a v4 JWT) from your API settings — this server authenticates v3 endpoints with Authorization: Bearer <token>, not the legacy ?api_key= query parameter.
Add the following to your MCP client configuration file.
{
"mcpServers": {
"tmdb-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/tmdb-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"TMDB_API_KEY": "your-tmdb-read-access-token"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"tmdb-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/tmdb-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"TMDB_API_KEY": "your-tmdb-read-access-token"
}
}
}
}Or with Docker:
{
"mcpServers": {
"tmdb-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "TMDB_API_KEY=your-tmdb-read-access-token",
"ghcr.io/cyanheads/tmdb-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 TMDB_API_KEY=... bun run start:http
# Server listens at http://localhost:3010/mcpRefer to "your MCP client configuration file" generically — different clients use different config paths, and this server isn't client-specific.
Prerequisites
- Bun v1.3.2 or higher (or Node.js v24+).
- A TMDB API Read Access Token (v4 JWT) — free from your TMDB API settings.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/tmdb-mcp-server.git- Navigate into the directory:
cd tmdb-mcp-server- Install dependencies:
bun install- Configure environment:
cp .env.example .env
# edit .env and set TMDB_API_KEYConfiguration
All configuration is validated at startup via Zod schemas. Key environment variables:
| Variable | Description | Default |
|:---|:---|:---|
| TMDB_API_KEY | Required. TMDB v4 API Read Access Token (JWT), sent as Authorization: Bearer. Not the v3 ?api_key= value. | — |
| TMDB_LANGUAGE | Default response language as ISO 639-1, optionally with region (e.g. en-US). A per-call language input overrides it. | en-US |
| TMDB_DEFAULT_REGION | Default ISO 3166-1 country hint used in region-aware error messages. tmdb_get_watch_providers still requires an explicit watch_region. | US |
| MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
| MCP_HTTP_PORT | Port for the HTTP server. | 3010 |
| MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
| MCP_LOG_LEVEL | Log level (RFC 5424). | info |
| STORAGE_PROVIDER_TYPE | Storage backend. | in-memory |
| OTEL_ENABLED | Enable OpenTelemetry instrumentation (spans, metrics, completion logs). | false |
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t tmdb-mcp-server .
docker run --rm -e TMDB_API_KEY=your-token -p 3010:3010 tmdb-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/tmdb-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|:---|:---|
| src/index.ts | createApp() entry point — registers tools and resources, and primes the startup cache in setup(). |
| src/config | Server-specific environment variable parsing and validation with Zod. |
| src/mcp-server/tools | Tool definitions (*.tool.ts) — the eight TMDB tools. |
| src/mcp-server/resources | Resource definitions (*.resource.ts) — movie, TV, and person detail. |
| src/services/tmdb | TMDB v3 REST client — Bearer auth, retry/timeout, the image/genre startup cache, and the imageUrl/genreNames helpers. |
| tests/ | Unit and integration tests mirroring src/. |
Development guide
See AGENTS.md (or CLAUDE.md, the same content) for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - Register new tools and resources via the barrels in
src/mcp-server/*/definitions/index.ts - Wrap the TMDB API: validate raw → normalize to the domain type → return the output schema; never fabricate missing fields (null poster paths omit the URL, unknown genre ids are dropped)
Contributing
Issues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This product uses the TMDB API but is not endorsed or certified by TMDB. Streaming availability data is provided by JustWatch via TMDB and is region-specific.
