Skip to main content
Glama
index.ts8.66 kB
#!/usr/bin/env node /** * Restream MCP Server * Provides Model Context Protocol tools for interacting with Restream API */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from '@modelcontextprotocol/sdk/types.js'; import dotenv from 'dotenv'; import { RestreamClient } from './restream-client.js'; import type { RestreamConfig } from './types.js'; // Load environment variables dotenv.config(); // Validate required environment variables const requiredEnvVars = ['RESTREAM_CLIENT_ID', 'RESTREAM_CLIENT_SECRET']; for (const envVar of requiredEnvVars) { if (!process.env[envVar]) { console.error(`Error: Missing required environment variable: ${envVar}`); process.exit(1); } } // Initialize Restream client const config: RestreamConfig = { clientId: process.env.RESTREAM_CLIENT_ID!, clientSecret: process.env.RESTREAM_CLIENT_SECRET!, baseUrl: process.env.RESTREAM_API_BASE_URL || 'https://api.restream.io/v2', }; const restreamClient = new RestreamClient(config); // Define MCP tools const tools: Tool[] = [ { name: 'get_user_profile', description: 'Get the authenticated user profile information including email, display name, and account details', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'list_channels', description: 'List all connected streaming channels/platforms (YouTube, Twitch, Facebook, etc.) with their connection status', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_channel', description: 'Get detailed information about a specific channel by ID', inputSchema: { type: 'object', properties: { channelId: { type: 'string', description: 'The ID of the channel to retrieve', }, }, required: ['channelId'], }, }, { name: 'update_channel_status', description: 'Enable or disable a specific streaming channel', inputSchema: { type: 'object', properties: { channelId: { type: 'string', description: 'The ID of the channel to update', }, enabled: { type: 'boolean', description: 'Whether to enable (true) or disable (false) the channel', }, }, required: ['channelId', 'enabled'], }, }, { name: 'get_current_stream', description: 'Get information about the current/active stream including title, status, RTMP URL, and viewer count', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'update_stream_settings', description: 'Update settings for the current stream such as title, description, or privacy settings', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'The stream title', }, description: { type: 'string', description: 'The stream description', }, privacy: { type: 'string', enum: ['public', 'private', 'unlisted'], description: 'The stream privacy setting', }, }, }, }, { name: 'get_stream_analytics', description: 'Get analytics and statistics for streams including viewer counts, engagement metrics, and performance data', inputSchema: { type: 'object', properties: { streamId: { type: 'string', description: 'Optional stream ID to get analytics for a specific stream. If not provided, returns analytics for the current user', }, }, }, }, { name: 'start_stream', description: 'Start a new stream with optional settings', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'The stream title', }, description: { type: 'string', description: 'The stream description', }, privacy: { type: 'string', enum: ['public', 'private', 'unlisted'], description: 'The stream privacy setting', }, }, }, }, { name: 'stop_stream', description: 'Stop the current active stream', inputSchema: { type: 'object', properties: {}, required: [], }, }, ]; // Create MCP server const server = new Server( { name: 'restream-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // Handle list tools request server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; }); // Handle tool execution server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'get_user_profile': { const profile = await restreamClient.getUserProfile(); return { content: [ { type: 'text', text: JSON.stringify(profile, null, 2), }, ], }; } case 'list_channels': { const channels = await restreamClient.getChannels(); return { content: [ { type: 'text', text: JSON.stringify(channels, null, 2), }, ], }; } case 'get_channel': { if (!args || typeof args.channelId !== 'string') { throw new Error('channelId is required'); } const channel = await restreamClient.getChannel(args.channelId); return { content: [ { type: 'text', text: JSON.stringify(channel, null, 2), }, ], }; } case 'update_channel_status': { if (!args || typeof args.channelId !== 'string' || typeof args.enabled !== 'boolean') { throw new Error('channelId and enabled are required'); } const channel = await restreamClient.updateChannelStatus(args.channelId, args.enabled); return { content: [ { type: 'text', text: JSON.stringify(channel, null, 2), }, ], }; } case 'get_current_stream': { const stream = await restreamClient.getCurrentStream(); return { content: [ { type: 'text', text: stream ? JSON.stringify(stream, null, 2) : 'No active stream', }, ], }; } case 'update_stream_settings': { if (!args) { throw new Error('At least one setting is required'); } const stream = await restreamClient.updateStreamSettings(args); return { content: [ { type: 'text', text: JSON.stringify(stream, null, 2), }, ], }; } case 'get_stream_analytics': { const analytics = await restreamClient.getStreamAnalytics( args && typeof args.streamId === 'string' ? args.streamId : undefined ); return { content: [ { type: 'text', text: JSON.stringify(analytics, null, 2), }, ], }; } case 'start_stream': { const stream = await restreamClient.startStream(args || {}); return { content: [ { type: 'text', text: JSON.stringify(stream, null, 2), }, ], }; } case 'stop_stream': { await restreamClient.stopStream(); return { content: [ { type: 'text', text: 'Stream stopped successfully', }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: 'text', text: `Error: ${errorMessage}`, }, ], isError: true, }; } }); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('Restream MCP Server running on stdio'); } main().catch((error) => { console.error('Fatal error:', error); process.exit(1); });

Latest Blog Posts

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/shaktech786/restream-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server