Skip to main content
Glama
mukiwu
by mukiwu

recommend_api_combination

Recommends optimal Web API combinations based on functional requirements, browser compatibility, and performance needs for JavaScript/TypeScript projects.

Instructions

根據自然語言描述的需求,推薦最佳的 API 技術組合

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
requirementYes功能需求描述 (例如:背景擷取影片畫面並分析)
targetBrowsersNo目標瀏覽器支援 (預設: 現代瀏覽器)
performanceRequirementsNo效能需求 (low/medium/high)medium

Implementation Reference

  • src/server.ts:145-170 (registration)
    Registration of the 'recommend_api_combination' tool in the ListTools handler, including its name, description, and input schema.
    {
      name: 'recommend_api_combination',
      description: '根據自然語言描述的需求,推薦最佳的 API 技術組合',
      inputSchema: {
        type: 'object',
        properties: {
          requirement: {
            type: 'string',
            description: '功能需求描述 (例如:背景擷取影片畫面並分析)',
          },
          targetBrowsers: {
            type: 'array',
            items: { type: 'string' },
            description: '目標瀏覽器支援 (預設: 現代瀏覽器)',
            default: ['chrome>=90', 'firefox>=88', 'safari>=14', 'edge>=90']
          },
          performanceRequirements: {
            type: 'string',
            description: '效能需求 (low/medium/high)',
            enum: ['low', 'medium', 'high'],
            default: 'medium'
          }
        },
        required: ['requirement'],
      },
    },
  • Main handler function for the 'recommend_api_combination' tool. Validates input, matches categories using CanIUseService, recommends APIs using ApiRecommendationKnowledge, fetches compatibility and baseline info, generates comprehensive report.
    private async handleApiRecommendation(args: unknown) {
      try {
        const validatedArgs = this.validateApiRecommendationArgs(args);
        const { requirement, targetBrowsers, performanceRequirements } = validatedArgs;
    
        // 步驟 1: 先取得所有可用的 API 類別
        let allCategories: Array<{ name: string; count: number; description?: string }> = [];
        let matchedCategories: string[] = [];
    
        try {
          allCategories = await this.canIUseService.getAllCategories();
    
          // 根據需求描述匹配相關的類別
          const lowerReq = requirement.toLowerCase();
          matchedCategories = allCategories
            .filter(cat => {
              const catName = cat.name.toLowerCase();
              const catDesc = (cat.description || '').toLowerCase();
              return lowerReq.includes(catName) ||
                catName.includes(lowerReq) ||
                catDesc.includes(lowerReq) ||
                this.matchCategoryKeywords(lowerReq, cat.name);
            })
            .map(cat => cat.name);
        } catch (error) {
          console.warn('無法取得類別列表,將使用預定義知識庫:', error);
        }
    
        // 步驟 2: 從匹配的類別中找出相關的 API
        const apisFromCategories = new Set<string>();
        for (const category of matchedCategories) {
          try {
            const featureIds = await this.canIUseService.getFeaturesByCategory(category);
            // 將 feature ID 轉換為 API 名稱(如果知識庫中有對應的)
            for (const featureId of featureIds.slice(0, 10)) { // 限制每個類別最多 10 個
              const api = this.apiKnowledge.getApiByCaniuseId(featureId);
              if (api) {
                apisFromCategories.add(api.name);
              }
            }
          } catch (error) {
            console.warn(`無法取得類別 ${category} 的 API:`, error);
          }
        }
    
        // 步驟 3: 從知識庫中推薦 API(原有邏輯)
        const recommendedApis = this.apiKnowledge.recommendApis(
          requirement,
          performanceRequirements
        );
    
        // 步驟 4: 合併結果,優先使用知識庫的推薦,補充類別匹配的結果
        const apiMap = new Map<string, RecommendedApi>();
    
        // 先加入知識庫推薦的 API
        for (const api of recommendedApis) {
          apiMap.set(api.name, api);
        }
    
        // 補充從類別匹配找到的 API(如果不在知識庫推薦中)
        for (const apiName of apisFromCategories) {
          const api = this.apiKnowledge.getApi(apiName);
          if (api && !apiMap.has(apiName)) {
            // 檢查是否符合需求描述
            const lowerReq = requirement.toLowerCase();
            if (api.description.toLowerCase().includes(lowerReq) ||
              api.useCases.some(uc => lowerReq.includes(uc.toLowerCase()))) {
              apiMap.set(apiName, api);
            }
          }
        }
    
        const finalRecommendedApis = Array.from(apiMap.values());
    
        if (finalRecommendedApis.length === 0) {
          let suggestionText = `# 🔍 API 推薦結果\n\n找不到與「${requirement}」相關的 API 推薦。\n\n`;
    
          if (matchedCategories.length > 0) {
            suggestionText += `**相關類別**: ${matchedCategories.join(', ')}\n\n`;
          }
    
          suggestionText += `**建議:**\n`;
          suggestionText += `- 嘗試使用更具體的描述\n`;
          suggestionText += `- 使用英文關鍵字(如 fetch, animation, storage)\n`;
          suggestionText += `- 描述具體的使用場景\n`;
          suggestionText += `- 使用 \`list_api_categories\` 工具查看所有可用的 API 類別\n`;
    
          return {
            content: [{
              type: 'text',
              text: suggestionText
            }]
          };
        }
    
        // 解析目標瀏覽器版本
        const browserVersions = this.parseBrowserVersions(targetBrowsers);
    
        // 為每個推薦的 API 查詢相容性
        const apiWithCompatibility = await this.fetchApiCompatibility(
          finalRecommendedApis,
          browserVersions
        );
    
        // 生成報告(包含類別資訊)
        const report = this.generateApiRecommendationReport(
          requirement,
          apiWithCompatibility,
          browserVersions,
          performanceRequirements,
          matchedCategories,
          allCategories.length
        );
    
        return {
          content: [{
            type: 'text',
            text: report
          }]
        };
    
      } catch (error) {
        const errorMessage = error instanceof ValidationError
          ? `參數驗證失敗: ${error.message}`
          : `推薦失敗: ${error instanceof Error ? error.message : String(error)}`;
    
        return {
          content: [{ type: 'text', text: errorMessage }],
          isError: true,
        };
      }
    }
  • Input schema definition for the recommend_api_combination tool.
    inputSchema: {
      type: 'object',
      properties: {
        requirement: {
          type: 'string',
          description: '功能需求描述 (例如:背景擷取影片畫面並分析)',
        },
        targetBrowsers: {
          type: 'array',
          items: { type: 'string' },
          description: '目標瀏覽器支援 (預設: 現代瀏覽器)',
          default: ['chrome>=90', 'firefox>=88', 'safari>=14', 'edge>=90']
        },
        performanceRequirements: {
          type: 'string',
          description: '效能需求 (low/medium/high)',
          enum: ['low', 'medium', 'high'],
          default: 'medium'
        }
      },
      required: ['requirement'],
  • Core recommendation logic using keyword mappings and API knowledge base. Called by the handler.
    recommendApis(requirement: string, performanceLevel?: 'low' | 'medium' | 'high'): RecommendedApi[] {
      const lowerReq = requirement.toLowerCase();
      const matchedApiNames = new Set<string>();
    
      // 根據關鍵字匹配
      for (const mapping of this.keywordMappings) {
        for (const keyword of mapping.keywords) {
          if (lowerReq.includes(keyword.toLowerCase())) {
            for (const apiName of mapping.apis) {
              matchedApiNames.add(apiName);
            }
          }
        }
      }
    
      // 直接搜尋 API 名稱
      for (const [name, api] of this.apis) {
        if (lowerReq.includes(name.toLowerCase()) ||
            api.useCases.some(uc => lowerReq.includes(uc.toLowerCase())) ||
            api.description.toLowerCase().includes(lowerReq)) {
          matchedApiNames.add(name);
        }
      }
    
      // 取得匹配的 API 資料
      let results: RecommendedApi[] = [];
      for (const name of matchedApiNames) {
        const api = this.apis.get(name);
        if (api) {
          results.push(api);
        }
      }
    
      // 根據效能需求過濾
      if (performanceLevel === 'high') {
        results = results.filter(api => api.performanceLevel === 'high');
      } else if (performanceLevel === 'low') {
        // low 需求可以使用任何 API
      }
    
      return results;
    }
  • Helper function that formats the final recommendation report with detailed API info, browser compatibility, and categorized suggestions.
    private generateApiRecommendationReport(
      requirement: string,
      apiWithCompatibility: Array<{
        api: RecommendedApi;
        compatibility: {
          globalSupport: number;
          supported: string[];
          notSupported: string[];
          partialSupport: string[];
          recommendation: string;
          polyfillAvailable: boolean;
          polyfillUrl?: string;
        } | null;
        baseline: {
          status: string;
          label: string;
          description: string;
          icon: string;
          safeToUse: boolean;
          recommendation: string;
        } | null;
      }>,
      targetBrowsers: Record<string, string>,
      performanceLevel?: string,
      matchedCategories?: string[],
      totalCategoriesCount?: number
    ): string {
      let report = `# 🎯 API 組合推薦\n\n`;
      report += `**需求**: ${requirement}\n`;
      report += `**目標瀏覽器**: ${Object.entries(targetBrowsers).map(([b, v]) => `${b} >= ${v}`).join(', ')}\n`;
      if (performanceLevel) {
        report += `**效能需求**: ${performanceLevel}\n`;
      }
    
      // 顯示類別分析資訊
      if (matchedCategories && matchedCategories.length > 0) {
        report += `**相關類別**: ${matchedCategories.join(', ')}\n`;
      }
      if (totalCategoriesCount) {
        report += `**可用類別總數**: ${totalCategoriesCount} 個(從 Can I Use 資料庫分析)\n`;
      }
    
      report += `\n---\n\n`;
    
      // 按類別分組
      const byCategory = new Map<string, typeof apiWithCompatibility>();
      for (const item of apiWithCompatibility) {
        const category = item.api.category;
        if (!byCategory.has(category)) {
          byCategory.set(category, []);
        }
        byCategory.get(category)!.push(item);
      }
    
      report += `## 📋 推薦 API 列表\n\n`;
      report += `共找到 **${apiWithCompatibility.length}** 個相關 API:\n\n`;
    
      for (const [category, items] of byCategory) {
        report += `### 📁 ${category}\n\n`;
    
        for (const { api, compatibility, baseline } of items) {
          // API 標題和支援狀態
          const supportIcon = compatibility
            ? (compatibility.notSupported.length === 0 ? '✅' :
              compatibility.supported.length > 0 ? '⚠️' : '❌')
            : '❓';
    
          // 如果有 Baseline 狀態,優先使用 Baseline 圖示
          const displayIcon = baseline ? baseline.icon : supportIcon;
    
          report += `#### ${displayIcon} ${api.name}\n\n`;
          report += `${api.description}\n\n`;
    
          // Baseline 狀態
          if (baseline) {
            report += `**📊 Baseline 狀態**: ${baseline.icon} **${baseline.label}**\n\n`;
            report += `${baseline.description}\n\n`;
            if (baseline.safeToUse) {
              report += `✅ **可安全使用** - 此 API 在所有核心瀏覽器中都支援\n\n`;
            } else {
              report += `⚠️ **需謹慎使用** - 建議檢查目標瀏覽器支援情況\n\n`;
            }
          }
    
          // 用途
          report += `**適用場景**: ${api.useCases.join('、')}\n\n`;
    
          // 程式碼範例
          report += `**程式碼範例**:\n\`\`\`javascript\n${api.codeExample}\n\`\`\`\n\n`;
    
          // 可取代的函式庫
          if (api.replacesLibraries && api.replacesLibraries.length > 0) {
            report += `**可取代函式庫**: ${api.replacesLibraries.map(l => `\`${l}\``).join(', ')}\n\n`;
          }
    
          // 相容性資訊
          if (compatibility) {
            report += `**🌐 瀏覽器相容性**:\n\n`;
            report += `- 全球支援率: **${compatibility.globalSupport.toFixed(1)}%**\n`;
    
            if (compatibility.supported.length > 0) {
              report += `- ✅ 支援: ${compatibility.supported.join(', ')}\n`;
            }
            if (compatibility.partialSupport.length > 0) {
              report += `- ⚠️ 部分支援: ${compatibility.partialSupport.join(', ')}\n`;
            }
            if (compatibility.notSupported.length > 0) {
              report += `- ❌ 不支援: ${compatibility.notSupported.join(', ')}\n`;
            }
    
            report += `\n${compatibility.recommendation}\n\n`;
    
            // Polyfill 資訊
            if (compatibility.polyfillAvailable) {
              report += `**🔧 Polyfill 可用**`;
              if (compatibility.polyfillUrl) {
                report += `:\n\`\`\`html\n<script src="${compatibility.polyfillUrl}"></script>\n\`\`\``;
              }
              report += '\n\n';
            }
          } else {
            report += `**🌐 瀏覽器相容性**: 無法取得相容性資料,請參考 [Can I Use](https://caniuse.com/?search=${encodeURIComponent(api.caniuseId)})\n\n`;
          }
    
          // 相關 API
          if (api.relatedApis && api.relatedApis.length > 0) {
            report += `**相關 API**: ${api.relatedApis.join(', ')}\n\n`;
          }
    
          report += `---\n\n`;
        }
      }
    
      // 總結建議
      report += `## 💡 實作建議\n\n`;
    
      // 添加類別分析說明
      if (matchedCategories && matchedCategories.length > 0) {
        report += `### 📊 類別分析\n\n`;
        report += `本推薦基於以下分析流程:\n\n`;
        report += `1. ✅ 從 Can I Use 資料庫取得所有 ${totalCategoriesCount || '可用'} 個 API 類別\n`;
        report += `2. ✅ 根據需求描述匹配相關類別:**${matchedCategories.join('**, **')}**\n`;
        report += `3. ✅ 從匹配類別中找出相關 API\n`;
        report += `4. ✅ 結合預定義知識庫的推薦結果\n`;
        report += `5. ✅ 查詢瀏覽器相容性並生成最終推薦\n\n`;
        report += `---\n\n`;
      }
    
      const fullySupported = apiWithCompatibility.filter(
        item => item.compatibility && item.compatibility.notSupported.length === 0
      );
      const needsPolyfill = apiWithCompatibility.filter(
        item => item.compatibility && item.compatibility.notSupported.length > 0 && item.compatibility.polyfillAvailable
      );
      const notSupported = apiWithCompatibility.filter(
        item => item.compatibility && item.compatibility.notSupported.length > 0 && !item.compatibility.polyfillAvailable
      );
    
      if (fullySupported.length > 0) {
        report += `### ✅ 可直接使用 (${fullySupported.length})\n`;
        report += `以下 API 在所有目標瀏覽器中都完全支援:\n`;
        for (const { api } of fullySupported) {
          report += `- ${api.name}\n`;
        }
        report += '\n';
      }
    
      if (needsPolyfill.length > 0) {
        report += `### ⚠️ 需要 Polyfill (${needsPolyfill.length})\n`;
        report += `以下 API 在部分目標瀏覽器中需要 polyfill:\n`;
        for (const { api, compatibility } of needsPolyfill) {
          report += `- ${api.name}`;
          if (compatibility?.polyfillUrl) {
            report += ` - [Polyfill](${compatibility.polyfillUrl})`;
          }
          report += '\n';
        }
        report += '\n';
      }
    
      if (notSupported.length > 0) {
        report += `### ❌ 需要替代方案 (${notSupported.length})\n`;
        report += `以下 API 在部分目標瀏覽器中不支援且無 polyfill:\n`;
        for (const { api } of notSupported) {
          report += `- ${api.name} - 建議尋找替代方案或調整目標瀏覽器\n`;
        }
        report += '\n';
      }
    
      return report;
    }
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 of behavioral disclosure. The description states it '推薦最佳的 API 技術組合' (recommends the best API technology combination), which implies a read-only, advisory function without mutations. However, it doesn't disclose key behavioral traits such as whether the recommendations are based on real-time data, require authentication, have rate limits, or what the output format might be (e.g., list of APIs with explanations). For a tool with no annotations, this is a significant gap in transparency.

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

Conciseness4/5

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

The description is concise and front-loaded, consisting of a single sentence: '根據自然語言描述的需求,推薦最佳的 API 技術組合' (Based on natural language described requirements, recommend the best API technology combination). It efficiently communicates the core purpose without unnecessary words. However, it could be slightly improved by adding a brief example or more context, but as-is, it's well-structured and to the point.

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 the complexity of recommending API combinations and the lack of annotations and output schema, the description is incomplete. It doesn't explain what the tool returns (e.g., a list of APIs, compatibility scores, or implementation steps), nor does it cover behavioral aspects like dependencies or limitations. With no output schema and minimal description, users or AI agents would lack crucial information to understand the tool's full context and results.

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?

The input schema has 100% description coverage, with clear documentation for all three parameters: 'requirement' (functional requirement description), 'targetBrowsers' (target browser support), and 'performanceRequirements' (performance needs). The description doesn't add any meaning beyond what the schema provides—it only mentions '自然語言描述的需求' (natural language described requirements), which aligns with the 'requirement' parameter but doesn't elaborate on syntax or examples. With high schema coverage, the baseline score of 3 is appropriate, as the description doesn't compensate but also doesn't detract.

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

Purpose4/5

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

The description clearly states the tool's purpose: 'recommend最佳的 API 技術組合' (recommend the best API technology combination) based on natural language requirements. It specifies the verb 'recommend' and the resource 'API technology combination', making the purpose understandable. However, it doesn't explicitly differentiate from sibling tools like 'analyze_compatibility' or 'search_mdn', which might have overlapping functionality.

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

Usage Guidelines2/5

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

The description provides minimal guidance on when to use this tool. It mentions '根據自然語言描述的需求' (based on natural language described requirements), which implies usage for general API recommendation scenarios. However, it doesn't specify when to use this versus alternatives like 'analyze_compatibility' for compatibility checks or 'list_api_categories' for browsing APIs, nor does it mention any exclusions or prerequisites. This lack of explicit context reduces its helpfulness.

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/mukiwu/dev-advisor-mcp'

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