Skip to main content
Glama

get_jw_captions

Extract video captions from JW.org content by providing a video ID or URL to access subtitles for religious study materials.

Instructions

Fetches video captions from JW.org by video ID or URL. Accepts either a direct video ID (e.g., "pub-jwbvod25_17_VIDEO") or a JW.org URL (e.g., "https://www.jw.org/finder?srcid=jwlshare&wtlocale=E&lank=pub-jwbvod25_17_VIDEO")

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
video_idYesThe JW.org video ID or a JW.org URL containing the video ID. If a URL is provided, the video ID will be automatically extracted.

Implementation Reference

  • Core handler function executing the get_jw_captions tool logic: extracts video ID, fetches JW.org media data and subtitles.
    export async function getCaptionsImplementation(video_id) {
      try {
        // Extract video ID from URL if needed
        const extractedVideoId = extractVideoId(video_id);
        
        // Step 1: Get JSON data for JW video
        const mediaUrl = `https://b.jw-cdn.org/apis/mediator/v1/media-items/E/${extractedVideoId}?clientType=www`;
        const mediaResponse = await fetch(mediaUrl);
        
        if (!mediaResponse.ok) {
          return {
            content: [
              {
                type: 'text',
                text: `Failed to fetch video data for ID "${extractedVideoId}": ${mediaResponse.statusText}`,
              },
            ],
          };
        }
    
        const mediaData = await mediaResponse.json();
    
        // Check if media exists and has files
        if (!mediaData.media || !mediaData.media[0] || !mediaData.media[0].files) {
          return {
            content: [
              {
                type: 'text',
                text: 'No media found for this video ID',
              },
            ],
          };
        }
    
        const media = mediaData.media[0];
        
        // Extract video metadata
        const title = media.title || 'Unknown Title';
        const thumbnail = media.images?.wss?.sm || '';
    
        // Check for subtitles URL
        const subtitlesUrl = media.files[1]?.subtitles?.url;
    
        if (!subtitlesUrl) {
          return {
            content: [
              {
                type: 'text',
                text: 'No subtitle file was found for this video. Unable to provide further info.',
              },
            ],
            isError: true,
          };
        }
    
        // Step 2: Get subtitles from JW.org
        const subtitlesResponse = await fetch(subtitlesUrl);
        
        if (!subtitlesResponse.ok) {
          return {
            content: [
              {
                type: 'text',
                text: `Failed to fetch subtitles: ${subtitlesResponse.statusText}`,
              },
            ],
          };
        }
    
        const subtitlesData = await subtitlesResponse.text();
    
        // Return the result matching the n8n workflow output
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify({
                title,
                thumbnail,
                subtitles: subtitlesData,
              }, null, 2),
            },
          ],
        };
    
      } catch (error) {
        return {
          content: [
            {
              type: 'text',
              text: `Error: ${error.message}`,
            },
          ],
          isError: true,
        };
      }
    }
  • Tool schema definition including name, description, and inputSchema for get_jw_captions.
    export const captionsTool = {
      name: 'get_jw_captions',
      description: 'Fetches video captions from JW.org by video ID or URL. Accepts either a direct video ID (e.g., "pub-jwbvod25_17_VIDEO") or a JW.org URL (e.g., "https://www.jw.org/finder?srcid=jwlshare&wtlocale=E&lank=pub-jwbvod25_17_VIDEO")',
      inputSchema: {
        type: 'object',
        properties: {
          video_id: {
            type: 'string',
            description: 'The JW.org video ID or a JW.org URL containing the video ID. If a URL is provided, the video ID will be automatically extracted.',
          },
        },
        required: ['video_id'],
      },
    };
  • Helper function to extract JW.org video ID from URL or return direct ID.
    function extractVideoId(input) {
      // If it's already a video ID (doesn't contain http/https), return as-is
      if (!input.includes('http')) {
        return input;
      }
      
      // Extract video ID from various JW.org URL formats
      try {
        const url = new URL(input);
        
        // Check for 'lank' parameter (most common format)
        const lank = url.searchParams.get('lank');
        if (lank) {
          return lank;
        }
        
        // Check for 'docid' parameter (alternative format)
        const docid = url.searchParams.get('docid');
        if (docid) {
          return docid;
        }
        
        // Check if video ID is in the pathname
        const pathMatch = url.pathname.match(/\/(pub-[^\/]+)/);
        if (pathMatch) {
          return pathMatch[1];
        }
        
        // If no video ID found, return the original input and let the API handle the error
        return input;
      } catch (error) {
        // If URL parsing fails, assume it's a direct video ID
        return input;
      }
    }
  • src/index.js:33-41 (registration)
    Registration of the tool schema (captionsTool) in the allTools array for ListToolsRequestHandler.
    const allTools = [
      captionsTool,
      ...workbookTools,
      ...watchtowerTools,
      searchBibleBooksTool,
      getBibleVerseTool,
      getVerseWithStudyTool,
      getBibleVerseURLTool
    ];
  • src/index.js:44-49 (registration)
    Registration of the tool handler (handleCaptionsTool) in the toolHandlers array for CallToolRequestHandler.
    const toolHandlers = [
      handleCaptionsTool,
      handleWorkbookTools,
      handleWatchtowerTools,
      handleScriptureTools
    ];
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It describes the input behavior (accepts ID or URL, extracts ID from URL) but does not disclose critical traits like authentication needs, rate limits, error handling, or output format. For a tool with no annotations, this leaves significant behavioral gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and efficiently uses two sentences to explain input formats with clear examples. Every sentence adds essential information without redundancy, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations, no output schema, and a single parameter with high schema coverage, the description is incomplete. It lacks information on output (e.g., caption format, structure), error cases, or behavioral constraints, which are crucial for a tool fetching external data. The description does not compensate for these gaps adequately.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents the parameter. The description adds value by explaining the semantics of 'video_id' (e.g., examples of ID and URL formats, automatic extraction from URL), but it does not provide additional details beyond what the schema implies. Baseline 3 is appropriate as the schema handles most documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('fetches video captions') and resource ('from JW.org by video ID or URL'), distinguishing it from sibling tools that focus on Bible verses, Watchtower, or workbook content. It precisely defines what the tool does without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by specifying input formats (video ID or URL) but does not explicitly state when to use this tool versus alternatives or provide context on prerequisites. It offers basic guidance but lacks explicit when/when-not directives or named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/advenimus/jw-mcp'

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