# Directory Structure ``` ├── .gitignore ├── LICENSE ├── package.json ├── README.md ├── src │ ├── index.ts │ └── types │ └── modelcontextprotocol.d.ts └── tsconfig.json ``` # Files -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- ``` 1 | # Dependencies 2 | node_modules/ 3 | package-lock.json 4 | 5 | # Build output 6 | dist/ 7 | 8 | # Environment variables 9 | .env 10 | .env.local 11 | .env.*.local 12 | 13 | # IDE - VSCode 14 | .vscode/ 15 | .idea/ 16 | 17 | # OS generated files 18 | .DS_Store 19 | .DS_Store? 20 | ._* 21 | .Spotlight-V100 22 | .Trashes 23 | ehthumbs.db 24 | Thumbs.db 25 | 26 | # Logs 27 | logs 28 | *.log 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | ``` -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- ```markdown 1 | # TMDB MCP Server 2 | 3 | A Model Context Protocol (MCP) server that provides access to The Movie Database (TMDB) API. This server enables AI assistants to search and retrieve movie information through the MCP interface. 4 | 5 | ## Features 6 | 7 | - Search movies by title, year, and other criteria 8 | - Retrieve detailed movie information 9 | - Easy integration with MCP-compatible AI assistants 10 | 11 | ## Prerequisites 12 | 13 | - Node.js >= 18 14 | - TMDB API key (get one from [TMDB](https://www.themoviedb.org/documentation/api)) 15 | 16 | ## Installation 17 | 18 | 1. Clone the repository: 19 | ```bash 20 | git clone https://github.com/rakeshgangwar/tmdb-mcp-server.git 21 | cd tmdb-mcp-server 22 | ``` 23 | 24 | 2. Install dependencies: 25 | ```bash 26 | npm install 27 | ``` 28 | 29 | 3. Build the server: 30 | ```bash 31 | npm run build 32 | ``` 33 | 34 | ## Configuration 35 | 36 | Configure the MCP server in your MCP settings file (typically `cline_mcp_settings.json`): 37 | 38 | ```json 39 | { 40 | "mcpServers": { 41 | "tmdb": { 42 | "command": "node", 43 | "args": ["/path/to/tmdb-mcp-server/dist/index.js"], 44 | "env": { 45 | "TMDB_API_KEY": "your-api-key-here" 46 | }, 47 | "disabled": false, 48 | "autoApprove": [] 49 | } 50 | } 51 | } 52 | ``` 53 | 54 | Replace `your-api-key-here` with your TMDB API key and replace `/path/to/` with actual path. 55 | 56 | ## Available Tools 57 | 58 | ### search_movies 59 | Search for movies using The Movie Database API. 60 | 61 | Parameters: 62 | - `query` (required): Search query string 63 | - `year` (optional): Filter by release year 64 | - `page` (optional): Page number (default: 1) 65 | 66 | Example: 67 | ```javascript 68 | { 69 | "query": "Inception", 70 | "year": 2010, 71 | "page": 1 72 | } 73 | ``` 74 | 75 | ## Development 76 | 77 | 1. Make your changes in the `src` directory 78 | 2. Build the project: 79 | ```bash 80 | npm run build 81 | ``` 82 | 83 | 3. Test your changes by configuring the MCP server in your settings 84 | 85 | ## Contributing 86 | 87 | 1. Fork the repository 88 | 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 89 | 3. Commit your changes (`git commit -am 'Add some amazing feature'`) 90 | 4. Push to the branch (`git push origin feature/amazing-feature`) 91 | 5. Open a Pull Request 92 | 93 | ## License 94 | 95 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 96 | 97 | ## Acknowledgments 98 | 99 | - [TMDB API](https://www.themoviedb.org/documentation/api) for providing the movie database API 100 | - [Model Context Protocol](https://github.com/modelcontextprotocol) for the MCP SDK 101 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "tmdb-mcp-server", 3 | "version": "1.0.0", 4 | "description": "TMDB MCP Server for accessing The Movie Database API", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "clean": "rm -rf dist", 8 | "prebuild": "npm run clean", 9 | "build": "tsc", 10 | "postbuild": "chmod +x dist/index.js" 11 | }, 12 | "type": "module", 13 | "devDependencies": { 14 | "@types/node": "^16.18.126", 15 | "typescript": "^5.8.2" 16 | }, 17 | "dependencies": { 18 | "@modelcontextprotocol/sdk": "1.7.0", 19 | "axios": "^1.8.3" 20 | } 21 | } 22 | ``` -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "es2020", 5 | "lib": ["es2020"], 6 | "outDir": "./dist", 7 | "rootDir": "./src", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "esModuleInterop": true, 11 | "skipLibCheck": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "allowSyntheticDefaultImports": true, 14 | "allowJs": true, 15 | "typeRoots": [ 16 | "./node_modules/@types", 17 | "./src/types" 18 | ], 19 | "noImplicitAny": false 20 | }, 21 | "include": ["src/**/*"], 22 | "exclude": ["node_modules", "dist"] 23 | } 24 | ``` -------------------------------------------------------------------------------- /src/types/modelcontextprotocol.d.ts: -------------------------------------------------------------------------------- ```typescript 1 | declare module '@modelcontextprotocol/sdk' { 2 | export class Server { 3 | constructor(info: { name: string; version: string }, options: { capabilities: { tools: any } }); 4 | setRequestHandler(schema: any, handler: Function): void; 5 | connect(transport: any): Promise<void>; 6 | } 7 | 8 | export class StdioServerTransport { 9 | constructor(); 10 | } 11 | 12 | export const CallToolRequestSchema: unique symbol; 13 | export const ListToolsRequestSchema: unique symbol; 14 | 15 | export interface CallToolRequest { 16 | params: { 17 | name: string; 18 | arguments?: Record<string, unknown>; 19 | }; 20 | } 21 | } 22 | ``` -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- ```typescript 1 | #!/usr/bin/env node 2 | import { Server } from '@modelcontextprotocol/sdk/server/index.js'; 3 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; 4 | import { 5 | CallToolRequestSchema, 6 | ErrorCode, 7 | ListToolsRequestSchema, 8 | McpError, 9 | } from '@modelcontextprotocol/sdk/types.js'; 10 | import axios from 'axios'; 11 | 12 | const TMDB_ACCESS_TOKEN = process.env.TMDB_ACCESS_TOKEN; 13 | if (!TMDB_ACCESS_TOKEN) { 14 | throw new Error('TMDB_ACCESS_TOKEN environment variable is required'); 15 | } 16 | 17 | class TMDBServer { 18 | private server: Server; 19 | private axiosInstance; 20 | 21 | constructor() { 22 | this.server = new Server( 23 | { 24 | name: 'tmdb-server', 25 | version: '0.1.0', 26 | }, 27 | { 28 | capabilities: { 29 | resources: {}, 30 | tools: {}, 31 | }, 32 | } 33 | ); 34 | 35 | this.axiosInstance = axios.create({ 36 | baseURL: 'https://api.themoviedb.org/3', 37 | headers: { 38 | 'Authorization': `Bearer ${TMDB_ACCESS_TOKEN}`, 39 | 'accept': 'application/json' 40 | }, 41 | }); 42 | 43 | this.setupToolHandlers(); 44 | 45 | this.server.onerror = (error) => console.error('[MCP Error]', error); 46 | process.on('SIGINT', async () => { 47 | await this.server.close(); 48 | process.exit(0); 49 | }); 50 | } 51 | 52 | private setupToolHandlers() { 53 | this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ 54 | tools: [ 55 | { 56 | name: 'search_movies', 57 | description: 'Search for movies using The Movie Database API', 58 | inputSchema: { 59 | type: 'object', 60 | properties: { 61 | query: { 62 | type: 'string', 63 | description: 'Search query', 64 | }, 65 | year: { 66 | type: 'number', 67 | description: 'Filter by release year (optional)', 68 | }, 69 | page: { 70 | type: 'number', 71 | description: 'Page number (default: 1)', 72 | }, 73 | }, 74 | required: ['query'], 75 | }, 76 | }, 77 | ], 78 | })); 79 | 80 | this.server.setRequestHandler(CallToolRequestSchema, async (request) => { 81 | if (request.params.name !== 'search_movies') { 82 | throw new McpError( 83 | ErrorCode.MethodNotFound, 84 | `Unknown tool: ${request.params.name}` 85 | ); 86 | } 87 | 88 | const args = request.params.arguments as { 89 | query: string; 90 | year?: number; 91 | page?: number; 92 | }; 93 | const { query, year, page = 1 } = args; 94 | 95 | try { 96 | const response = await this.axiosInstance.get('/search/movie', { 97 | params: { 98 | query, 99 | year, 100 | page, 101 | }, 102 | }); 103 | 104 | return { 105 | content: [ 106 | { 107 | type: 'text', 108 | text: JSON.stringify(response.data, null, 2), 109 | }, 110 | ], 111 | }; 112 | } catch (error) { 113 | if (axios.isAxiosError(error)) { 114 | return { 115 | content: [ 116 | { 117 | type: 'text', 118 | text: `TMDB API error: ${ 119 | error.response?.data.message ?? error.message 120 | }`, 121 | }, 122 | ], 123 | isError: true, 124 | }; 125 | } 126 | throw error; 127 | } 128 | }); 129 | } 130 | 131 | async run() { 132 | const transport = new StdioServerTransport(); 133 | await this.server.connect(transport); 134 | console.error('TMDB MCP server running on stdio'); 135 | } 136 | } 137 | 138 | const server = new TMDBServer(); 139 | server.run().catch(console.error); 140 | ```