Skip to main content
Glama
mukiwu
by mukiwu

check_browser_support

Check browser compatibility for Web APIs using Can I Use database to identify supported versions and polyfill recommendations.

Instructions

使用 Can I Use 資料庫檢查 Web API 的瀏覽器相容性,取得支援版本和 polyfill 建議

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
featureYesWeb API 功能名稱,如 "fetch", "flexbox", "css-grid", "webgl"
targetBrowsersNo目標瀏覽器版本 (預設: { chrome: "90", firefox: "88", safari: "14", edge: "90" })

Implementation Reference

  • src/server.ts:219-237 (registration)
    Registration of the 'check_browser_support' tool including its input schema and description in the ListToolsRequestSchema handler
    {
      name: 'check_browser_support',
      description: '使用 Can I Use 資料庫檢查 Web API 的瀏覽器相容性,取得支援版本和 polyfill 建議',
      inputSchema: {
        type: 'object',
        properties: {
          feature: {
            type: 'string',
            description: 'Web API 功能名稱,如 "fetch", "flexbox", "css-grid", "webgl"',
          },
          targetBrowsers: {
            type: 'object',
            description: '目標瀏覽器版本 (預設: { chrome: "90", firefox: "88", safari: "14", edge: "90" })',
            default: { chrome: '90', firefox: '88', safari: '14', edge: '90' }
          }
        },
        required: ['feature'],
      },
    },
  • Core implementation of browser support checking using Can I Use database. Matches the tool's input parameters (feature, targetBrowsers) and returns compatibility report with support status, polyfills etc.
    async checkCompatibility(
      featureId: string,
      targetBrowsers: Record<string, string> = {
        chrome: '90',
        firefox: '88',
        safari: '14',
        edge: '90'
      }
    ): Promise<CompatibilityReport> {
      const support = await this.getFeatureSupport(featureId);
    
      if (!support) {
        return {
          feature: featureId,
          globalSupport: 0,
          supported: [],
          notSupported: Object.keys(targetBrowsers),
          partialSupport: [],
          recommendation: `找不到 ${featureId} 的相容性資料,建議查詢 MDN 文件`,
          polyfillAvailable: false
        };
      }
    
      const supported: string[] = [];
      const notSupported: string[] = [];
      const partialSupport: string[] = [];
    
      for (const [browser, targetVersion] of Object.entries(targetBrowsers)) {
        const browserSupport = (support.browsers as any)[browser];
    
        if (!browserSupport) {
          notSupported.push(browser);
          continue;
        }
    
        if (browserSupport.supported) {
          if (browserSupport.sinceVersion) {
            const sinceNum = parseFloat(browserSupport.sinceVersion);
            const targetNum = parseFloat(targetVersion);
    
            if (sinceNum <= targetNum) {
              if (browserSupport.partialSupport) {
                partialSupport.push(`${browser} >= ${browserSupport.sinceVersion}`);
              } else {
                supported.push(`${browser} >= ${browserSupport.sinceVersion}`);
              }
            } else {
              notSupported.push(`${browser} < ${browserSupport.sinceVersion}`);
            }
          } else {
            supported.push(browser);
          }
        } else {
          notSupported.push(browser);
        }
      }
    
      // 生成建議
      let recommendation = '';
      if (notSupported.length === 0) {
        recommendation = '✅ 所有目標瀏覽器都支援此功能';
      } else if (supported.length === 0) {
        recommendation = '❌ 此功能在目標瀏覽器中不受支援,需要 polyfill 或替代方案';
      } else {
        recommendation = `⚠️ 部分瀏覽器不支援:${notSupported.join(', ')}。建議提供 fallback 或使用 polyfill`;
      }
    
      return {
        feature: support.title,
        globalSupport: support.usage,
        supported,
        notSupported,
        partialSupport,
        recommendation,
        polyfillAvailable: this.checkPolyfillAvailable(featureId),
        polyfillUrl: this.getPolyfillUrl(featureId)
      };
    }
  • Helper method to search for Can I Use feature IDs by name, used prior to checking support
    async searchFeature(query: string): Promise<string[]> {
      const data = await this.loadData();
      const features = data.data || {};
      const lowerQuery = query.toLowerCase();
    
      const matches: { id: string; score: number }[] = [];
    
      for (const [id, feature] of Object.entries(features) as [string, any][]) {
        let score = 0;
    
        // 完全匹配 ID
        if (id.toLowerCase() === lowerQuery) {
          score = 100;
        }
        // ID 包含查詢
        else if (id.toLowerCase().includes(lowerQuery)) {
          score = 80;
        }
        // 標題匹配
        else if (feature.title?.toLowerCase().includes(lowerQuery)) {
          score = 60;
        }
        // 描述匹配
        else if (feature.description?.toLowerCase().includes(lowerQuery)) {
          score = 40;
        }
        // 關鍵字匹配
        else if (feature.keywords?.toLowerCase().includes(lowerQuery)) {
          score = 30;
        }
    
        if (score > 0) {
          matches.push({ id, score });
        }
      }
    
      // 按分數排序並返回 ID
      return matches
        .sort((a, b) => b.score - a.score)
        .slice(0, 10)
        .map(m => m.id);
    }
  • Instantiation of CanIUseService used for browser support checks
    this.canIUseService = new CanIUseService();
    this.baselineService = new BaselineService();
  • Comprehensive handler for compatibility checks (case 'check_compatibility') that performs feature search and browser support analysis using CanIUseService, closely matching the tool's purpose despite name difference
    private async handleCompatibilityCheck(args: unknown) {
      try {
        if (!args || typeof args !== 'object') {
          throw new ValidationError('參數格式錯誤');
        }
    
        const {
          feature,
          targetBrowsers = { chrome: '90', firefox: '88', safari: '14', edge: '90' }
        } = args as Record<string, unknown>;
    
        if (typeof feature !== 'string' || !feature.trim()) {
          throw new ValidationError('feature 為必填欄位,請提供要檢查的 Web API 功能名稱');
        }
    
        // 同時查詢 Can I Use 和 Baseline
        const [caniuseMatches, baselineMatches] = await Promise.all([
          this.canIUseService.searchFeature(feature),
          this.baselineService.searchFeature(feature)
        ]);
    
        // 如果兩個來源都找不到
        if (caniuseMatches.length === 0 && baselineMatches.length === 0) {
          return {
            content: [{
              type: 'text',
              text: `🔍 相容性查詢結果\n\n找不到與 "${feature}" 相關的功能。\n\n建議:\n- 嘗試使用不同的關鍵字\n- 常見功能名稱:fetch, flexbox, css-grid, webgl, es6-module, async-functions`
            }]
          };
        }
    
        let report = `# 🌐 Web API 相容性報告: ${feature}\n\n`;
    
        // ========== Can I Use 資料 ==========
        if (caniuseMatches.length > 0) {
          const featureSupport = await this.canIUseService.getFeatureSupport(caniuseMatches[0]);
    
          if (featureSupport) {
            const compatReport = await this.canIUseService.checkCompatibility(
              caniuseMatches[0],
              targetBrowsers as Record<string, string>
            );
    
            report += `## 📊 概覽\n\n`;
            report += `- **功能**: ${featureSupport.title}\n`;
            report += `- **全球支援率**: ${compatReport.globalSupport.toFixed(1)}%\n`;
            report += `- **標準狀態**: ${this.getStatusText(featureSupport.status)}\n`;
    
            if (featureSupport.description) {
              report += `\n### 說明\n${featureSupport.description}\n`;
            }
    
            report += `\n## 🎯 目標瀏覽器相容性\n\n`;
            report += `${compatReport.recommendation}\n\n`;
    
            if (compatReport.supported.length > 0) {
              report += `### ✅ 支援的瀏覽器\n`;
              for (const browser of compatReport.supported) {
                report += `- ${browser}\n`;
              }
              report += '\n';
            }
    
            if (compatReport.partialSupport.length > 0) {
              report += `### ⚠️ 部分支援\n`;
              for (const browser of compatReport.partialSupport) {
                report += `- ${browser}\n`;
              }
              report += '\n';
            }
    
            if (compatReport.notSupported.length > 0) {
              report += `### ❌ 不支援\n`;
              for (const browser of compatReport.notSupported) {
                report += `- ${browser}\n`;
              }
              report += '\n';
            }
    
            // Polyfill 資訊
            if (compatReport.polyfillAvailable) {
              report += `## 🔧 Polyfill\n\n`;
              report += `此功能有 polyfill 可用。\n`;
              if (compatReport.polyfillUrl) {
                report += `\n\`\`\`html\n<script src="${compatReport.polyfillUrl}"></script>\n\`\`\`\n`;
              }
              report += '\n';
            }
    
            // 各瀏覽器詳細支援版本
            report += `## 📱 各瀏覽器支援版本\n\n`;
            const browsers = featureSupport.browsers;
    
            const browserNames: Record<string, string> = {
              chrome: 'Chrome',
              firefox: 'Firefox',
              safari: 'Safari',
              edge: 'Edge',
              ie: 'Internet Explorer',
              opera: 'Opera',
              ios_saf: 'iOS Safari',
              android: 'Android Browser',
              samsung: 'Samsung Internet'
            };
    
            for (const [key, name] of Object.entries(browserNames)) {
              const support = (browsers as any)[key];
              if (support) {
                const icon = support.supported ? '✅' : (support.partialSupport ? '⚠️' : '❌');
                const version = support.sinceVersion ? `v${support.sinceVersion}+` : (support.supported ? '支援' : '不支援');
                report += `| ${icon} ${name} | ${version} |\n`;
              }
            }
            report += '\n';
          }
        }
    
        // ========== Baseline 狀態 ==========
        report += `## 📊 Baseline 狀態\n\n`;
    
        if (baselineMatches.length > 0) {
          const baselineInfo = await this.baselineService.getFeature(baselineMatches[0].id) || baselineMatches[0];
    
          if (baselineInfo.baseline) {
            report += this.baselineService.formatBaselineInfo(baselineInfo);
            report += `\n${this.baselineService.getRecommendation(baselineInfo)}\n\n`;
    
            // Baseline 的瀏覽器支援資訊
            if (baselineInfo.compat) {
              report += `### Baseline 瀏覽器支援\n\n`;
              const compat = baselineInfo.compat;
    
              if (compat.chrome) {
                const since = compat.chrome.since || '未知';
                const flags = compat.chrome.flags ? ' (需要啟用實驗性功能)' : '';
                report += `- **Chrome**: ${since}${flags}\n`;
              }
              if (compat.firefox) {
                const since = compat.firefox.since || '未知';
                const flags = compat.firefox.flags ? ' (需要啟用實驗性功能)' : '';
                report += `- **Firefox**: ${since}${flags}\n`;
              }
              if (compat.safari) {
                const since = compat.safari.since || '未知';
                const flags = compat.safari.flags ? ' (需要啟用實驗性功能)' : '';
                report += `- **Safari**: ${since}${flags}\n`;
              }
              if (compat.edge) {
                const since = compat.edge.since || '未知';
                const flags = compat.edge.flags ? ' (需要啟用實驗性功能)' : '';
                report += `- **Edge**: ${since}${flags}\n`;
              }
              report += '\n';
            }
          } else {
            report += `❓ 此功能尚未有 Baseline 狀態資訊\n\n`;
          }
        } else {
          report += `❓ 在 Baseline 資料庫中找不到此功能\n\n`;
          report += `建議查閱 [web.dev/baseline](https://web.dev/baseline) 確認。\n\n`;
        }
    
        // ========== 相關連結 ==========
        report += `## 🔗 相關連結\n\n`;
        if (caniuseMatches.length > 0) {
          report += `- [Can I Use](https://caniuse.com/${caniuseMatches[0]})\n`;
        }
        if (baselineMatches.length > 0 && baselineMatches[0].mdn?.url) {
          report += `- [MDN 文件](${baselineMatches[0].mdn.url})\n`;
        }
        report += `- [Baseline 狀態](https://web.dev/baseline)\n`;
    
        // 其他相關功能
        const allMatches = [...new Set([...caniuseMatches.slice(1, 4), ...baselineMatches.slice(1, 4).map(m => m.name)])];
        if (allMatches.length > 0) {
          report += `\n## 🔍 其他相關功能\n\n`;
          report += `您可能也在尋找:\n`;
          for (const match of allMatches.slice(0, 5)) {
            report += `- \`${typeof match === 'string' ? match : match}\`\n`;
          }
        }
    
        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,
        };
      }
    }
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. It mentions checking compatibility and getting support versions and polyfill recommendations, but lacks details on response format, error handling, rate limits, authentication needs, or whether it's a read-only operation. For a tool with no annotation coverage, this leaves significant gaps in understanding its behavior.

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 a single, efficient sentence in Chinese that front-loads the core purpose and key outputs. Every word earns its place: it specifies the data source (Can I Use database), action (check compatibility), target (Web API), and outputs (support versions and polyfill recommendations). There is no wasted verbiage or redundancy.

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 tool's complexity (checking browser compatibility with polyfill recommendations), lack of annotations, and no output schema, the description is incomplete. It doesn't explain what the return values look like (e.g., structured data on browser support percentages, polyfill links), error conditions, or limitations. For a tool with no structured behavioral data, more descriptive context is needed to be fully helpful.

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 both parameters ('feature' and 'targetBrowsers') with descriptions and defaults. The description adds no additional parameter semantics beyond implying the tool uses the Can I Use database, which is context but not parameter-specific. With high schema coverage, the baseline score of 3 is appropriate as the description doesn't enhance parameter understanding.

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: '使用 Can I Use 資料庫檢查 Web API 的瀏覽器相容性,取得支援版本和 polyfill 建議' (Use Can I Use database to check Web API browser compatibility, get support versions and polyfill recommendations). It specifies the verb ('檢查' - check), resource ('Web API 的瀏覽器相容性' - Web API browser compatibility), and data source ('Can I Use 資料庫'). However, it doesn't explicitly differentiate from sibling tools like 'analyze_compatibility' or 'analyze_modernization', which likely 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 no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like 'analyze_compatibility' or 'search_mdn', nor does it specify prerequisites, exclusions, or typical use cases. The agent must infer usage from the purpose alone, which is insufficient for optimal tool selection.

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