Skip to main content
Glama
yshk-mrt

Presentation Buddy MCP Server

by yshk-mrt

PlayPauseMedia

Control media playback in presentations by playing, pausing, stopping, or restarting video and audio sources during streaming automation.

Instructions

Controls playback of a media source (play, pause, stop, restart). 用途: 動画クリップやオーディオの再生制御

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paramsYes

Implementation Reference

  • The handler function for the 'PlayPauseMedia' tool. It extracts sourceName and mediaAction from parameters, converts mediaAction to uppercase, and sends a 'TriggerMediaInputAction' request to the OBS WebSocket via sendToObs. Returns success or error structured content.
    case "PlayPauseMedia":
        const mediaParams = params as { sourceName: string; mediaAction: string };
        console.log(`Executing PlayPauseMedia with params:`, mediaParams);
        try {
            await sendToObs("TriggerMediaInputAction", { inputName: mediaParams.sourceName, mediaAction: mediaParams.mediaAction.toUpperCase() }, context, action.name);
            return { structuredContent: { success: true } };
        } catch (e: any) {
            console.error(`Error in PlayPauseMedia for OBS:`, e.message);
            return { structuredContent: { success: false, error: e.message } };
        }
  • src/index.ts:364-991 (registration)
    Dynamic registration of tools from toolDefinitions JSON. The 'PlayPauseMedia' tool is registered here via server.tool() with its name, description, schema (derived from JSON), and a shared handler function that uses a switch on action.name to dispatch to specific logic.
        server.tool(
            action.name,
            action.description || "",
            requestSchema ? { params: requestSchema } : {},
            async (params: any, context: any) => { // Using any for context if ToolContext is not easily available
                console.log(`Tool '${action.name}' called with params:`, JSON.stringify(params, null, 2));
                try {
                    // Ensure OBS is connected before attempting to send a command
                    if (!obsClient || obsClient.readyState !== WebSocket.OPEN) {
                        if (!isObsConnecting) {
                            console.log("OBS not connected. Attempting to connect before processing tool action.");
                            await connectToObs(); // This will throw if it fails
                            if (!obsClient || obsClient.readyState !== WebSocket.OPEN) {
                                throw new Error("Failed to connect to OBS.");
                            }
                        } else {
                            // Wait for existing connection attempt
                            await obsConnectionPromise;
                             if (!obsClient || obsClient.readyState !== WebSocket.OPEN) {
                                throw new Error("Failed to connect to OBS after waiting.");
                            }
                        }
                    }
    
    
                    let obsResponseData: any;
                    // Map MCP actions to OBS requestTypes and params
                    switch (action.name) {
                        case "SwitchScene":
                            console.log("SwitchScene params:", JSON.stringify(params, null, 2));
                            // Extract the scene name from the parameters
                            const sceneName = params.scene || (params.params && params.params.scene);
                            console.log("Extracted sceneName:", sceneName);
                            
                            if (!sceneName) {
                                throw new Error("No scene name provided");
                            }
                            
                            try {
                                // NOTE: Changed from SetCurrentProgramScene to use the direct parameters expected by OBS
                                obsResponseData = await sendToObs(
                                    "SetCurrentProgramScene", 
                                    { "sceneName": sceneName }, // Make sure we use the exact field name OBS expects
                                    context,
                                    action.name
                                );
                                console.log("OBS response:", JSON.stringify(obsResponseData, null, 2));
                            } catch (error) {
                                console.error("OBS error:", error);
                                throw error;
                            }
                            break;
                        case "StartStream":
                            obsResponseData = await sendToObs("StartStream", {}, context, action.name);
                            break;
                        case "StopStream":
                            obsResponseData = await sendToObs("StopStream", {}, context, action.name);
                            break;
                        case "StartRecording":
                            obsResponseData = await sendToObs("StartRecord", {}, context, action.name);
                            break;
                        case "StopRecording":
                            obsResponseData = await sendToObs("StopRecord", {}, context, action.name);
                            break;
                        case "SetSourceVisibility":
                            console.log("SetSourceVisibility params:", JSON.stringify(params, null, 2));
                            // Try different parameter access patterns
                            const sourceScene = params.scene || (params.params && params.params.scene);
                            const sourceName = params.source || (params.params && params.params.source);
                            const visible = params.visible !== undefined ? params.visible : 
                                           (params.params && params.params.visible !== undefined ? params.params.visible : null);
                            
                            if (!sourceScene || !sourceName || visible === null) {
                                throw new Error("Missing required parameters: scene, source, or visible");
                            }
    
                            const sceneItemIdResponse = await sendToObs<{ sceneItemId: number }>(
                                "GetSceneItemId",
                                { sceneName: sourceScene, sourceName: sourceName },
                                context,
                                action.name
                            );
                            obsResponseData = await sendToObs(
                                "SetSceneItemEnabled",
                                { sceneName: sourceScene, sceneItemId: sceneItemIdResponse.sceneItemId, sceneItemEnabled: visible },
                                context,
                                action.name
                            );
                            break;
                        case "GetSceneItemList":
                            // Extract sceneName from params
                            const sceneNameForItems = params.sceneName || params.scene || (params.params && (params.params.sceneName || params.params.scene));
                            if (!sceneNameForItems) {
                                throw new Error("Missing required parameter: sceneName");
                            }
                            obsResponseData = await sendToObs(
                                "GetSceneItemList",
                                { sceneName: sceneNameForItems },
                                context,
                                action.name
                            );
                            // Transform isGroup: null to isGroup: false to match schema
                            if (obsResponseData && Array.isArray(obsResponseData.sceneItems)) {
                                obsResponseData.sceneItems.forEach((item: any) => {
                                    if (item.isGroup === null) {
                                        item.isGroup = false;
                                    }
                                });
                            }
                            break;
                        case "GetSceneList":
                            obsResponseData = await sendToObs("GetSceneList", {}, context, action.name);
                            break;
                        case "SetTextContent":
                            console.log("SetTextContent params:", JSON.stringify(params, null, 2));
                            // Extract parameters
                            const textSourceName = params.source || (params.params && params.params.source);
                            const textContent = params.text || (params.params && params.params.text);
                            
                            if (!textSourceName || textContent === undefined) {
                                throw new Error("Missing required parameters: source or text");
                            }
                            
                            console.log(`Setting text content for source "${textSourceName}" to: ${textContent}`);
                            
                            try {
                                // Use SetInputSettings to update the text property
                                obsResponseData = await sendToObs(
                                    "SetInputSettings",
                                    { 
                                        inputName: textSourceName, 
                                        inputSettings: { 
                                            text: textContent 
                                        }
                                    },
                                    context,
                                    action.name
                                );
                                console.log("SetTextContent response:", JSON.stringify(obsResponseData, null, 2));
                            } catch (error) {
                                console.error("Error setting text content:", error);
                                throw error;
                            }
                            break;
                        case "SetAudioMute":
                            console.log("SetAudioMute params:", JSON.stringify(params, null, 2));
                            // Extract parameters
                            const audioSourceName = params.source || (params.params && params.params.source);
                            const muteState = params.mute !== undefined ? params.mute : 
                                             (params.params && params.params.mute !== undefined ? params.params.mute : null);
                            
                            if (!audioSourceName || muteState === null) {
                                throw new Error("Missing required parameters: source or mute");
                            }
                            
                            console.log(`Setting mute state for source "${audioSourceName}" to: ${muteState}`);
                            
                            try {
                                obsResponseData = await sendToObs(
                                    "SetInputMute",
                                    { 
                                        inputName: audioSourceName, 
                                        inputMuted: muteState 
                                    },
                                    context,
                                    action.name
                                );
                                console.log("SetAudioMute response:", JSON.stringify(obsResponseData, null, 2));
                            } catch (error) {
                                console.error("Error setting audio mute state:", error);
                                throw error;
                            }
                            break;
                        case "SetAudioVolume":
                            console.log("SetAudioVolume params:", JSON.stringify(params, null, 2));
                            // Extract parameters
                            const volumeSourceName = params.source || (params.params && params.params.source);
                            const volumeLevel = params.volume !== undefined ? params.volume : 
                                              (params.params && params.params.volume !== undefined ? params.params.volume : null);
                            
                            if (!volumeSourceName || volumeLevel === null) {
                                throw new Error("Missing required parameters: source or volume");
                            }
                            
                            if (volumeLevel < 0 || volumeLevel > 1) {
                                throw new Error("Volume must be between 0.0 and 1.0");
                            }
                            
                            console.log(`Setting volume for source "${volumeSourceName}" to: ${volumeLevel}`);
                            
                            try {
                                obsResponseData = await sendToObs(
                                    "SetInputVolume",
                                    { 
                                        inputName: volumeSourceName, 
                                        inputVolumeMul: volumeLevel  // Using multiplier (0.0 to 1.0) format
                                    },
                                    context,
                                    action.name
                                );
                                console.log("SetAudioVolume response:", JSON.stringify(obsResponseData, null, 2));
                            } catch (error) {
                                console.error("Error setting audio volume:", error);
                                throw error;
                            }
                            break;
                        case "SetSourcePosition":
                            console.log("SetSourcePosition params:", JSON.stringify(params, null, 2));
                            // Extract parameters
                            const posSceneName = params.scene || (params.params && params.params.scene);
                            const posSourceName = params.source || (params.params && params.params.source);
                            const xPos = params.x !== undefined ? params.x : 
                                       (params.params && params.params.x !== undefined ? params.params.x : null);
                            const yPos = params.y !== undefined ? params.y : 
                                       (params.params && params.params.y !== undefined ? params.params.y : null);
                            
                            if (!posSceneName || !posSourceName || xPos === null || yPos === null) {
                                throw new Error("Missing required parameters: scene, source, x, or y");
                            }
                            
                            console.log(`Setting position for source "${posSourceName}" in scene "${posSceneName}" to: x=${xPos}, y=${yPos}`);
                            
                            try {
                                // First get the scene item ID
                                const posItemIdResponse = await sendToObs<{ sceneItemId: number }>(
                                    "GetSceneItemId",
                                    { sceneName: posSceneName, sourceName: posSourceName },
                                    context,
                                    action.name
                                );
                                
                                // Then set the position
                                obsResponseData = await sendToObs(
                                    "SetSceneItemTransform",
                                    { 
                                        sceneName: posSceneName, 
                                        sceneItemId: posItemIdResponse.sceneItemId,
                                        sceneItemTransform: {
                                            positionX: xPos,
                                            positionY: yPos
                                        }
                                    },
                                    context,
                                    action.name
                                );
                                console.log("SetSourcePosition response:", JSON.stringify(obsResponseData, null, 2));
                            } catch (error) {
                                console.error("Error setting source position:", error);
                                throw error;
                            }
                            break;
                        case "SetSourceScale":
                            console.log("SetSourceScale params:", JSON.stringify(params, null, 2));
                            // Extract parameters
                            const scaleSceneName = params.scene || (params.params && params.params.scene);
                            const scaleSourceName = params.source || (params.params && params.params.source);
                            const scaleX = params.scaleX !== undefined ? params.scaleX : 
                                         (params.params && params.params.scaleX !== undefined ? params.params.scaleX : null);
                            const scaleY = params.scaleY !== undefined ? params.scaleY : 
                                         (params.params && params.params.scaleY !== undefined ? params.params.scaleY : null);
                            
                            if (!scaleSceneName || !scaleSourceName || scaleX === null || scaleY === null) {
                                throw new Error("Missing required parameters: scene, source, scaleX, or scaleY");
                            }
                            
                            console.log(`Setting scale for source "${scaleSourceName}" in scene "${scaleSceneName}" to: scaleX=${scaleX}, scaleY=${scaleY}`);
                            
                            try {
                                // First get the scene item ID
                                const scaleItemIdResponse = await sendToObs<{ sceneItemId: number }>(
                                    "GetSceneItemId",
                                    { sceneName: scaleSceneName, sourceName: scaleSourceName },
                                    context,
                                    action.name
                                );
                                
                                // Then set the scale
                                obsResponseData = await sendToObs(
                                    "SetSceneItemTransform",
                                    { 
                                        sceneName: scaleSceneName, 
                                        sceneItemId: scaleItemIdResponse.sceneItemId,
                                        sceneItemTransform: {
                                            scaleX: scaleX,
                                            scaleY: scaleY
                                        }
                                    },
                                    context,
                                    action.name
                                );
                                console.log("SetSourceScale response:", JSON.stringify(obsResponseData, null, 2));
                            } catch (error) {
                                console.error("Error setting source scale:", error);
                                throw error;
                            }
                            break;
                        case "TakeSourceScreenshot":
                            // Try to get source from params or params.params
                            const mcpInputParams = params.params || params;
                            const sourceNameForScreenshot = mcpInputParams.source; // Assuming 'source' is the key from MCP
    
                            if (!sourceNameForScreenshot) {
                                console.error("TakeSourceScreenshot Error: Missing required parameter 'source'. Params received:", JSON.stringify(params, null, 2));
                                throw new Error("Missing required parameter: source");
                            }
                            
                            // Ensure sourceNameForScreenshot is a string before calling replace
                            if (typeof sourceNameForScreenshot !== 'string') {
                                console.error("TakeSourceScreenshot Error: 'source' parameter is not a string. Value:", sourceNameForScreenshot);
                                throw new Error("'source' parameter must be a string.");
                            }
    
                            console.log(`Executing TakeSourceScreenshot for source: ${sourceNameForScreenshot}`);
    
                            const format = mcpInputParams.imageFormat || "png";
                            const timestamp = Date.now();
                            const filename = `screenshot-${sourceNameForScreenshot.replace(/[^a-z0-9]/gi, '_')}-${timestamp}.${format}`;
                            const absoluteFilePath = path.join(SCREENSHOTS_DIR_ABS, filename);
                            
                            // URI that will be returned to the client
                            const resourceUri = `file://${absoluteFilePath}`;
    
                            console.log(`Attempting to save screenshot to: ${absoluteFilePath}`);
    
                            try {
                                const obsRequestData: any = {
                                    sourceName: sourceNameForScreenshot, // OBS uses sourceName for SaveSourceScreenshot
                                    imageFormat: format,
                                    imageFilePath: absoluteFilePath, 
                                };
                                if (mcpInputParams.width !== undefined) obsRequestData.imageWidth = mcpInputParams.width;
                                if (mcpInputParams.height !== undefined) obsRequestData.imageHeight = mcpInputParams.height;
                                if (mcpInputParams.compressionQuality !== undefined) obsRequestData.imageCompressionQuality = mcpInputParams.compressionQuality;
    
                                // Use SaveSourceScreenshot OBS request
                                const obsResponse = await sendToObs("SaveSourceScreenshot", obsRequestData, context, "TakeSourceScreenshot");
                                
                                console.log(`SaveSourceScreenshot OBS response:`, obsResponse); 
                                console.log(`Screenshot for source ${sourceNameForScreenshot} saved to ${absoluteFilePath}. Returning URI: ${resourceUri}`);
                                
                                // Return the URI to the client as a resource
                                return {
                                    content: [{
                                        type: "resource",
                                        resource: {
                                            uri: resourceUri,
                                            text: `Screenshot for ${sourceNameForScreenshot} available at ${filename}`,
                                            // mimeType: `image/${format}` // Optional: include mimeType if known
                                        }
                                    }],
                                    filename: filename // Additional top-level info
                                };
    
                            } catch (e: any) {
                                console.error(`Error in TakeSourceScreenshot for source ${sourceNameForScreenshot}:`, e.message);
                                throw new Error(`Failed to take screenshot for ${sourceNameForScreenshot}: ${e.message}`);
                            }
                            break;
                        case "SetTransitionSettings":
                            const transitionParams = params as { transitionName: string; transitionDuration: number };
                            console.log(`Executing SetTransitionSettings with params:`, transitionParams);
                            try {
                                await sendToObs("SetCurrentSceneTransition", { transitionName: transitionParams.transitionName }, context, action.name);
                                await sendToObs("SetCurrentSceneTransitionSettings", { transitionSettings: { duration: transitionParams.transitionDuration }, overlay: false }, context, action.name);
                                return { structuredContent: { success: true } };
                            } catch (e: any) {
                                console.error(`Error in SetTransitionSettings for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "TriggerStudioModeTransition":
                            console.log(`Executing TriggerStudioModeTransition`);
                            try {
                                await sendToObs("TriggerStudioModeTransition", {}, context, action.name);
                                return { structuredContent: { success: true } };
                            } catch (e: any) {
                                console.error(`Error in TriggerStudioModeTransition for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "PlayPauseMedia":
                            const mediaParams = params as { sourceName: string; mediaAction: string };
                            console.log(`Executing PlayPauseMedia with params:`, mediaParams);
                            try {
                                await sendToObs("TriggerMediaInputAction", { inputName: mediaParams.sourceName, mediaAction: mediaParams.mediaAction.toUpperCase() }, context, action.name);
                                return { structuredContent: { success: true } };
                            } catch (e: any) {
                                console.error(`Error in PlayPauseMedia for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "SetMediaTime":
                            const timeParams = params as { sourceName: string; mediaTime: number };
                            console.log(`Executing SetMediaTime with params:`, timeParams);
                            try {
                                await sendToObs("SetMediaInputCursor", { inputName: timeParams.sourceName, mediaCursor: timeParams.mediaTime }, context, action.name);
                                return { structuredContent: { success: true } };
                            } catch (e: any) {
                                console.error(`Error in SetMediaTime for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "SaveReplayBuffer":
                            console.log(`Executing SaveReplayBuffer`);
                            try {
                                await sendToObs("SaveReplayBuffer", {}, context, action.name);
                                return { structuredContent: { success: true } };
                            } catch (e: any) {
                                console.error(`Error in SaveReplayBuffer for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "SaveReplayBufferAndAdd":
                            const replayParams = params as { sceneName: string; sourceName: string; replayFolder?: string };
                            console.log(`Executing SaveReplayBufferAndAdd with params:`, replayParams);
                            try {
                                // 1. Save the replay buffer
                                await sendToObs("SaveReplayBuffer", {}, context, action.name);
                                
                                // 2. Wait a bit for the file to be written to disk
                                await new Promise(resolve => setTimeout(resolve, 2000));
                                
                                // 3. Find the latest replay file
                                const defaultRecordingPath = process.env.OBS_REPLAY_PATH || path.join(os.homedir(), 'Movies');
                                const replayFolder = replayParams.replayFolder || defaultRecordingPath;
                                console.log(`Looking for the latest replay file in: ${replayFolder}`);
                                
                                // Get a list of replay files in the directory
                                let files: string[] = [];
                                try {
                                    files = fs.readdirSync(replayFolder)
                                        .filter(file => file.toLowerCase().includes('replay') && (file.endsWith('.mp4') || file.endsWith('.mov')))
                                        .map(file => path.join(replayFolder, file));
                                        
                                    // Sort by modification time, newest first
                                    files.sort((a, b) => {
                                        return fs.statSync(b).mtime.getTime() - fs.statSync(a).mtime.getTime();
                                    });
                                    
                                    console.log(`Found ${files.length} replay files`);
                                } catch (fsError: any) {
                                    console.error(`Error reading replay directory ${replayFolder}:`, fsError.message);
                                    return { structuredContent: { success: false, error: `Failed to read replay directory: ${fsError.message}` } };
                                }
                                
                                if (files.length === 0) {
                                    return { structuredContent: { success: false, error: "No replay files found" } };
                                }
                                
                                // Get the most recent file
                                const latestReplayFile = files[0];
                                console.log(`Latest replay file: ${latestReplayFile}`);
                                
                                // 4. Create a media source with this file
                                const mediaSourceResponse = await sendToObs<{ sceneItemId: number }>("CreateInput", {
                                    sceneName: replayParams.sceneName,
                                    inputName: replayParams.sourceName,
                                    inputKind: "ffmpeg_source",
                                    inputSettings: {
                                        local_file: latestReplayFile,
                                        looping: true
                                    },
                                    sceneItemEnabled: true
                                }, context, action.name);
                                
                                console.log(`Created media source with ID: ${mediaSourceResponse.sceneItemId}`);
                                return { 
                                    structuredContent: { 
                                        success: true, 
                                        filePath: latestReplayFile,
                                        sceneItemId: mediaSourceResponse.sceneItemId 
                                    } 
                                };
                            } catch (e: any) {
                                console.error(`Error in SaveReplayBufferAndAdd for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "CreateSource":
                            const sourceParams = params as { sceneName: string; sourceName: string; sourceKind: string; sourceSettings: object; setVisible?: boolean };
                            console.log(`Executing CreateSource with params:`, sourceParams);
                            try {
                                const response = await sendToObs<{ sceneItemId: number }>("CreateInput", {
                                    sceneName: sourceParams.sceneName,
                                    inputName: sourceParams.sourceName,
                                    inputKind: sourceParams.sourceKind,
                                    inputSettings: sourceParams.sourceSettings,
                                    sceneItemEnabled: typeof sourceParams.setVisible === 'boolean' ? sourceParams.setVisible : true
                                }, context, action.name);
                                return { structuredContent: { success: true, sceneItemId: response.sceneItemId } };
                            } catch (e: any) {
                                console.error(`Error in CreateSource for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "SetShaderFilter":
                            const shaderParams = params as { 
                                sourceName: string; 
                                filterName: string; 
                                shaderCode?: string; 
                                shaderParameters?: Record<string, any> 
                            };
                            console.log(`Executing SetShaderFilter with params:`, shaderParams);
                            try {
                                // Directly construct filterSettings without GetSourceFilterInfo
                                const filterSettings: Record<string, any> = {};
                                
                                if (shaderParams.shaderCode) {
                                    // The actual key for shader code might depend on the specific shader filter plugin.
                                    // Common ones are 'shader_text', 'glsl', or 'code'.
                                    // Assuming 'shader_text' based on common OBS shader filter plugins.
                                    filterSettings.shader_text = shaderParams.shaderCode; 
                                }
                                
                                if (shaderParams.shaderParameters) {
                                    // Shader parameters are often applied directly at the root of filterSettings
                                    // or under a specific key like 'defaults'.
                                    // This assumes they are direct key-value pairs.
                                    for (const [key, value] of Object.entries(shaderParams.shaderParameters)) {
                                        filterSettings[key] = value;
                                    }
                                }
                                
                                // Apply the constructed filter settings
                                await sendToObs(
                                    "SetSourceFilterSettings", 
                                    {
                                        sourceName: shaderParams.sourceName,
                                        filterName: shaderParams.filterName,
                                        filterSettings: filterSettings
                                    },
                                    context,
                                    action.name
                                );
                                
                                console.log(`Successfully attempted to update shader filter settings for ${shaderParams.filterName} on ${shaderParams.sourceName}`);
                                return { structuredContent: { success: true } };
                            } catch (e: any) {
                                console.error(`Error in SetShaderFilter for OBS:`, e.message);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        case "SetLutFilter":
                            console.log(`Executing SetLutFilter with params:`, JSON.stringify(params, null, 2));
                            try {
                                // Parse the input parameters
                                // Check if params are directly in params or in a nested params object
                                const paramsObj = params.params || params;
                                const sourceName = paramsObj.sourceName;
                                const filterName = paramsObj.filterName;
                                const amount = paramsObj.amount;
                                const path = paramsObj.path;
                                
                                console.log(`SetLutFilter: Parsed parameters - sourceName: "${sourceName}", filterName: "${filterName}", amount: ${amount}, path: ${path || "undefined"}`);
                                
                                if (!sourceName || !filterName) {
                                    throw new Error("Missing required parameters: sourceName or filterName");
                                }
                                
                                console.log(`SetLutFilter: Setting LUT filter "${filterName}" on source "${sourceName}"`);
                                
                                // Direct approach - skip getting current settings
                                console.log("Using direct filter update approach");
                                
                                const filterSettings: Record<string, any> = {};
                                
                                if (amount !== undefined) {
                                    filterSettings.amount = amount;
                                }
                                
                                if (path) {
                                    filterSettings.path = path;
                                }
                                
                                console.log(`Filter settings to apply:`, JSON.stringify(filterSettings, null, 2));
                                
                                const setFilterResponse = await sendToObs(
                                    "SetSourceFilterSettings", 
                                    {
                                        sourceName: sourceName,
                                        filterName: filterName,
                                        filterSettings: filterSettings
                                    },
                                    context,
                                    action.name
                                );
                                
                                console.log(`SetSourceFilterSettings response:`, JSON.stringify(setFilterResponse, null, 2));
                                console.log(`Successfully updated LUT filter settings directly for ${filterName} on ${sourceName}`);
                                return { structuredContent: { success: true } };
                            } catch (e: any) {
                                console.error(`Error in SetLutFilter for OBS:`, e.message);
                                console.error(`Error details:`, e);
                                return { structuredContent: { success: false, error: e.message } };
                            }
                        default:
                            console.error(`Unknown MCP action: ${action.name}`);
                            throw new Error(`Action '${action.name}' is not implemented.`);
                    }
                    
                    // ★★★ デバッグログ追加箇所 ★★★
                    console.log(`DEBUG: Formatting response for action: '${action.name}'`);
                    console.log(`DEBUG: obsResponseData content for MCP: ${JSON.stringify(obsResponseData, null, 2)}`);
                    // ★★★ここまで★★★
    
                    // Return the appropriate response format based on the action
                    if (action.name === "GetSceneItemList") {
                        // EXPERIMENT: Return as content to test Claude client behavior
                        console.log(`DEBUG: Formatting GetSceneItemList response as 'content' for Claude client test.`);
                        return {
                            content: [{ type: "text", text: JSON.stringify(obsResponseData, null, 2) }]
                        };
                    } else if (action.name === "GetSceneList") {
                        // For GetSceneList, return the full response as content
                        return {
                            content: [
                                { type: "text", text: JSON.stringify(obsResponseData, null, 2) }
                            ]
                        };
                    } else {
                        // For other actions, return a simple success message
                        return {
                            content: [
                                { type: "text", text: `Action '${action.name}' executed successfully.` }
                            ]
                        };
                    }
    
                } catch (error: any) {
                    console.error(`Error executing tool '${action.name}':`, error);
                    throw error; 
                }
            }
        );
        console.log(`Registered tool: ${action.name}`);
    });

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/yshk-mrt/obs-mcp'

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