diff --git a/package-lock.json b/package-lock.json index 7941157..31cd5c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@supadata/mcp", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@supadata/mcp", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.15.1", + "@modelcontextprotocol/sdk": "^1.17.3", "@supadata/js": "^1.3.0", "dotenv": "^16.4.7", "express": "^5.1.0", @@ -17,9 +17,6 @@ "ws": "^8.18.1", "zod": "^3.25.76" }, - "bin": { - "supadata-mcp": "dist/index.js" - }, "devDependencies": { "@jest/globals": "^29.7.0", "@types/express": "^5.0.1", diff --git a/package.json b/package.json index a0e9c26..ba40b5b 100644 --- a/package.json +++ b/package.json @@ -3,20 +3,17 @@ "version": "1.0.1", "description": "MCP server for Supadata video & web scraping integration. Features include YouTube, TikTok, Instagram, Twitter, and file video transcription, web scraping, batch processing and structured data extraction.", "type": "module", - "module": "./src/index.ts", - "bin": { - "supadata-mcp": "dist/index.js" - }, - "files": [ - "dist" - ], - "publishConfig": { - "access": "public" - }, + "module": "src/index.ts", "scripts": { - "build": "tsc && node -e \"require('fs').chmodSync('dist/index.js', '755')\"", + "dev": "npx @smithery/cli dev", + "build": "npm run build:http", + "build:stdio": "tsc", + "build:http": "npx @smithery/cli build", + "start": "npm run start:http", + "start:http": "node .smithery/index.cjs", + "start:stdio": "RUN_STDIO=true node dist/index.js", + "prepublishOnly": "npm run build:stdio", "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js", - "start": "node dist/index.js", "lint": "eslint src/**/*.ts", "lint:fix": "eslint src/**/*.ts --fix", "format": "prettier --write .", @@ -25,7 +22,7 @@ }, "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.15.1", + "@modelcontextprotocol/sdk": "^1.17.3", "@supadata/js": "^1.3.0", "dotenv": "^16.4.7", "express": "^5.1.0", @@ -68,4 +65,4 @@ "url": "https://github.com/supadata-ai/mcp/issues" }, "homepage": "https://github.com/supadata-ai/mcp#readme" -} \ No newline at end of file +} diff --git a/smithery.yaml b/smithery.yaml index 4d97551..8c93739 100644 --- a/smithery.yaml +++ b/smithery.yaml @@ -1,17 +1 @@ -# Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml - -startCommand: - type: stdio - configSchema: - # JSON Schema defining the configuration options for the MCP. - type: object - required: - - supadataApiKey - properties: - supadataApiKey: - type: string - description: Your Supadata API key. - commandFunction: - # A function that produces the CLI command to start the MCP on stdio. - |- - (config) => ({ command: 'node', args: ['dist/index.js'], env: { SUPADATA_API_KEY: config.supadataApiKey } }) +runtime: 'typescript' diff --git a/src/index.ts b/src/index.ts index a0f60e2..e835572 100644 --- a/src/index.ts +++ b/src/index.ts @@ -123,18 +123,22 @@ async function withRetry( } } -export default function createServer() { +export default function createServer({ + config, +}: { + config: z.infer; +}) { const server = new McpServer({ name: '@supadata/mcp', version: '1.0.0', }); // Get API key - const SUPADATA_API_KEY = process.env.SUPADATA_API_KEY; + const SUPADATA_API_KEY = config.supadataApiKey; // Check if API key is provided - if (!SUPADATA_API_KEY && process.env.CLOUD_SERVICE !== 'true') { - console.error('Error: SUPADATA_API_KEY environment variable is required'); + if (!SUPADATA_API_KEY) { + console.error('Error: SUPADATA_API_KEY is required'); process.exit(1); } @@ -166,16 +170,8 @@ export default function createServer() { **Supported Platforms:** YouTube, TikTok, Instagram, Twitter, and file URLs`, transcriptInputSchema, async ({ url, lang, text, chunkSize, mode }) => { - const apiKey = process.env.CLOUD_SERVICE - ? process.env.SUPADATA_API_KEY - : SUPADATA_API_KEY; - - if (process.env.CLOUD_SERVICE && !apiKey) { - throw new Error('No API key provided'); - } - const client = new Supadata({ - apiKey: apiKey as string, + apiKey: SUPADATA_API_KEY as string, }); try { @@ -261,16 +257,8 @@ export default function createServer() { **Tip:** Poll this endpoint periodically until status is 'completed' or 'failed'.`, checkTranscriptStatusInputSchema, async ({ id }) => { - const apiKey = process.env.CLOUD_SERVICE - ? process.env.SUPADATA_API_KEY - : SUPADATA_API_KEY; - - if (process.env.CLOUD_SERVICE && !apiKey) { - throw new Error('No API key provided'); - } - const client = new Supadata({ - apiKey: apiKey as string, + apiKey: SUPADATA_API_KEY as string, }); const response = await client.transcript.getJobStatus(id); @@ -314,16 +302,8 @@ export default function createServer() { - List of URLs found on the page`, scrapeInputSchema, async ({ url, noLinks, lang }) => { - const apiKey = process.env.CLOUD_SERVICE - ? process.env.SUPADATA_API_KEY // In cloud service mode, get from env - : SUPADATA_API_KEY; - - if (process.env.CLOUD_SERVICE && !apiKey) { - throw new Error('No API key provided'); - } - const client = new Supadata({ - apiKey: apiKey as string, + apiKey: SUPADATA_API_KEY as string, }); try { @@ -378,16 +358,8 @@ export default function createServer() { **Returns:** Array of URLs found on the website.`, mapInputSchema, async ({ url }) => { - const apiKey = process.env.CLOUD_SERVICE - ? process.env.SUPADATA_API_KEY - : SUPADATA_API_KEY; - - if (process.env.CLOUD_SERVICE && !apiKey) { - throw new Error('No API key provided'); - } - const client = new Supadata({ - apiKey: apiKey as string, + apiKey: SUPADATA_API_KEY as string, }); const response = await client.web.map(url); @@ -435,16 +407,8 @@ export default function createServer() { **Important:** Respect robots.txt and website terms of service when crawling web content.`, crawlInputSchema, async ({ url, limit }) => { - const apiKey = process.env.CLOUD_SERVICE - ? process.env.SUPADATA_API_KEY - : SUPADATA_API_KEY; - - if (process.env.CLOUD_SERVICE && !apiKey) { - throw new Error('No API key provided'); - } - const client = new Supadata({ - apiKey: apiKey as string, + apiKey: SUPADATA_API_KEY as string, }); const response = await withRetry( @@ -497,16 +461,8 @@ export default function createServer() { **Tip:** Poll this endpoint periodically until status is 'completed' or 'failed'.`, checkCrawlStatusInputSchema, async ({ id }) => { - const apiKey = process.env.CLOUD_SERVICE - ? process.env.SUPADATA_API_KEY - : SUPADATA_API_KEY; - - if (process.env.CLOUD_SERVICE && !apiKey) { - throw new Error('No API key provided'); - } - const client = new Supadata({ - apiKey: apiKey as string, + apiKey: SUPADATA_API_KEY as string, }); const response = await client.web.getCrawlResults(id); @@ -525,28 +481,23 @@ export default function createServer() { return server.server; } -// Server startup -async function runServer() { - try { - console.error('Initializing Supadata MCP Server...'); - - const server = createServer(); - const transport = new StdioServerTransport(); - - console.error('Running in stdio mode, logging will be directed to stderr'); +async function main() { + // Create server with configuration + const server = createServer({ + config: { + supadataApiKey: process.env.SUPADATA_API_KEY || '', + debug: process.env.DEBUG === 'true', + }, + }); - await server.connect(transport); + const transport = new StdioServerTransport(); + await server.connect(transport); + console.error('MCP Server running in stdio mode'); +} - console.error('Supadata MCP Server initialized successfully'); - console.error('Supadata MCP Server running on stdio'); - } catch (error) { - console.error('Fatal error running server:', error); +if (process.env.RUN_STDIO) { + main().catch((error) => { + console.error('Server error:', error); process.exit(1); - } + }); } - -// Only run the server if this file is executed directly -runServer().catch((error: any) => { - console.error('Fatal error running server:', error); - process.exit(1); -});