@cyanheads/tmdb-mcp-server
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 |
| Search movies, TV, and people by name. The required first step — resolves a name to the integer id the detail tools consume. |
| Full movie detail in one call — synopsis, runtime, genres, US certification, budget/revenue, cast, crew, trailers, recommendations, keywords, external ids. |
| Full TV show detail — overview, air dates, status, season/episode counts, creators, networks, season summaries, cast, trailers, content rating. |
| Episode list for one season — names, air dates, runtimes, vote averages, stills, per-episode guest stars, plus the season's regular cast. |
| Person detail and full filmography — biography, vital dates, the |
| Filtered, sorted discovery across movies or TV — the power-query: genre, date/vote ranges, vote-count floor, cast/crew/network, watch providers, runtime, sort. |
| Trending movies, TV, or people for the day or week. |
| 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 rankingOptional
yearfilter (movie/tv modes),languageoverride,include_adulttoggle, andpagefor paging past the first 20Each result carries
id,media_type, title/name,release_year,overview,vote_average, resolvedgenre_names, and the relevant poster/profile URLAn 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 URLsDoes 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_datesAdds 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 enrichmentIMDb 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, andruntimerangeSort 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 dominatewith_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 linksA
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 caveatAn 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 |
| Movie detail by id, as injectable context — the same enriched record as |
Resource |
| Show detail by id — the same enriched record as |
Resource |
| Person detail and filmography by id — the same record as |
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,oauthSwappable storage backends:
in-memory,filesystem,Supabase,Cloudflare KV/R2/D1Structured 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: BearerImage
*_pathfields resolved to fullhttps://image.tmdb.org/t/p/{size}{path}URLs — null paths omit the field rather than emitting a broken URLgenre_ids[]resolved to genre names from per-media_typemaps cached at startup, so list results carry readable genres without an extra callDetail tools collapse credits, videos, recommendations, similar, keywords, and external ids into one HTTP call via
append_to_responseRegion-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 surfacesProvenance 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.0 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.gitNavigate into the directory:
cd tmdb-mcp-serverInstall dependencies:
bun installConfigure 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 |
| Required. TMDB v4 API Read Access Token (JWT), sent as | — |
| Default response language as ISO 639-1, optionally with region (e.g. |
|
| Default ISO 3166-1 country hint used in region-aware error messages. |
|
| Transport: |
|
| Port for the HTTP server. |
|
| Auth mode: |
|
| Log level (RFC 5424). |
|
| Storage backend. |
|
| Enable OpenTelemetry instrumentation (spans, metrics, completion logs). |
|
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 |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| TMDB v3 REST client — Bearer auth, retry/timeout, the image/genre startup cache, and the |
| Unit and integration tests mirroring |
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 logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources via the barrels in
src/mcp-server/*/definitions/index.tsWrap 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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/tmdb-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server