Skip to main content
Glama
kesslerio

YOURLS-MCP

by kesslerio

get_url_keyword

Extract keywords from a long URL to identify its unique short link identifier. Optionally return a single result for precise URL management within the YOURLS-MCP server.

Instructions

Get the keyword(s) for a long URL

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
exactly_oneNoWhether to return only one result (default: false)
urlYesThe URL to find keywords for

Implementation Reference

  • The execute handler function that implements the core logic of the 'get_url_keyword' tool, processing input, calling the YOURLS client, and formatting the response.
    execute: async ({ url, exactly_one = true }) => {
      try {
        // Normalize boolean parameter if it's passed as a string
        if (typeof exactly_one === 'string') {
          exactly_one = exactly_one.toLowerCase() === 'true';
        }
        
        // Use the getUrlKeyword method with fallback enabled
        const result = await yourlsClient.getUrlKeyword(url, exactly_one, true);
        
        if (result.status === 'success' || result.message === 'success: found') {
          const responseData = {
            url: url
          };
          
          // Add keyword information based on response format
          if (exactly_one && result.keyword) {
            responseData.keyword = result.keyword;
            if (result.shorturl) responseData.shorturl = result.shorturl;
            if (result.title) responseData.title = result.title;
          } else if (!exactly_one && result.keywords) {
            responseData.keywords = result.keywords;
          }
          
          // Add message if available
          if (result.simple) responseData.message = result.simple;
          
          // Add fallback information if applicable
          if (result.fallback_used) {
            responseData.fallback_used = true;
            if (result.fallback_limitations) {
              responseData.fallback_limitations = result.fallback_limitations;
            }
          }
          
          return createMcpResponse(true, responseData);
        } else {
          throw new Error(result.message || 'Unknown error');
        }
      } catch (error) {
        return createMcpResponse(false, {
          message: error.message,
          url: url
        });
      }
    }
  • Input schema definition for the 'get_url_keyword' tool parameters.
    inputSchema: {
      type: 'object',
      properties: {
        url: {
          type: 'string',
          description: 'The long URL to look up'
        },
        exactly_one: {
          type: 'boolean',
          description: 'If false, returns all keywords for this URL (default: true)'
        }
      },
      required: ['url']
    },
  • src/index.js:211-217 (registration)
    Registration of the 'get_url_keyword' tool with the MCP server, including Zod schema conversion and binding the execute handler.
    getUrlKeywordTool.name,
    getUrlKeywordTool.description,
    {
      url: z.string().describe('The URL to find keywords for'),
      exactly_one: z.boolean().optional().describe('Whether to return only one result (default: false)')
    },
    getUrlKeywordTool.execute
  • The YourlsClient.getUrlKeyword method called by the tool handler, with plugin detection and fallback logic.
    async getUrlKeyword(url, exactlyOne = true, useNativeFallback = true) {
      const params = { url };
      
      if (!exactlyOne) {
        params.exactly_one = 'false';
      }
      
      try {
        // First check if the plugin is available
        const isAvailable = await isPluginAvailable(this, 'edit_url', 'geturl', { url: 'https://example.com' });
        
        if (isAvailable) {
          return this.request('geturl', params);
        } else if (useNativeFallback) {
          // Use our fallback implementation
          return this._getUrlKeywordFallback(url, exactlyOne);
        } else {
          throw new Error('The geturl action is not available. Please install the API Edit URL plugin.');
        }
      } catch (error) {
        // If the error is not about a missing plugin, re-throw it
        if (!isPluginMissingError(error)) {
          throw error;
        }
        
        // If we're here, the plugin is missing and we need to use the fallback
        if (useNativeFallback) {
          return this._getUrlKeywordFallback(url, exactlyOne);
        } else {
          throw new Error('The geturl action is not available. Please install the API Edit URL plugin.');
        }
      }
  • Fallback implementation _getUrlKeywordFallback used when the API Edit URL plugin is unavailable, searches via stats API.
    async _getUrlKeywordFallback(url, exactlyOne) {
      try {
        // Safety limit to prevent performance issues
        const MAX_RESULTS = 1000;
        
        // We can try to use the stats action with a filter
        const listResult = await this.request('stats', { 
          limit: MAX_RESULTS,
          filter: 'url',
          search: encodeURIComponent(url) 
        });
        
        // Process the results to match the geturl plugin's output format
        const keywords = [];
        let urlExists = false;
        
        if (listResult.links) {
          // Iterate through the results and find exact URL matches
          for (const [keyword, data] of Object.entries(listResult.links)) {
            if (data.url === url) {
              urlExists = true;
              keywords.push({
                keyword: keyword,
                shorturl: `${this.api_url.replace('yourls-api.php', '')}${keyword}`,
                title: data.title,
                url: data.url,
                date: data.timestamp,
                ip: data.ip,
                clicks: data.clicks
              });
              
              // If we only want one result and we found it, break
              if (exactlyOne) {
                break;
              }
            }
          }
        }
        
        // Format the response similarly to what the geturl plugin would return
        if (urlExists) {
          if (exactlyOne && keywords.length > 0) {
            // Return just the first match
            return {
              status: 'success',
              keyword: keywords[0].keyword,
              url: keywords[0].url,
              title: keywords[0].title,
              shorturl: keywords[0].shorturl,
              message: 'success',
              ...createFallbackInfo('Search limited to latest URLs', false, 'API Edit URL')
            };
          } else {
            // Return all matches
            return {
              status: 'success',
              keywords: keywords,
              url: url,
              message: 'success',
              ...createFallbackInfo('Search limited to latest URLs', false, 'API Edit URL')
            };
          }
        } else {
          // No matches found
          return {
            status: 'fail',
            message: 'URL not found',
            ...createFallbackInfo('Search limited to latest URLs', false, 'API Edit URL')
          };
        }
      } catch (error) {
        console.error('Get URL keyword fallback error:', error.message);
        
        // In case of fallback failure, return a safe default
        return {
          status: 'fail',
          message: 'Error looking up URL: ' + error.message,
          ...createFallbackInfo('Error during fallback search', true, 'API Edit URL')
        };
      }
    }
Install Server

Other Tools

Related 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/kesslerio/yourls-mcp'

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