Skip to main content
Glama

web_search

Perform web or news searches using Bing to find information, tutorials, or current events with time-based filtering options.

Instructions

Perform web or news search using Bing search engine. Supports both general web search and news search modes.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch query, e.g., Node.js tutorial, tech news, political updates, etc.
searchTypeYesSearch type: web (general web search), news (news search) - required
maxResultsNoMaximum number of results
timeFilterNoTime filter (only valid for news search): past 1 hour, 24 hours, 7 days, 30 dayspast_24_hours

Implementation Reference

  • Main MCP tool handler for web_search. Validates input parameters and delegates to searchService for Bing web or news search.
    async function handleWebSearch(args) {
      const { query, searchType, maxResults = 10, timeFilter = 'past_24_hours' } = args;
      
      if (!query || typeof query !== 'string') {
        throw new Error('Query parameter is required and must be a string');
      }
    
      if (!searchType || !['web', 'news'].includes(searchType)) {
        throw new Error('searchType is required and must be either "web" or "news"');
      }
    
      if (maxResults < 1 || maxResults > 20) {
        throw new Error('maxResults must be between 1 and 20');
      }
    
      if (searchType === 'news' && !['past_hour', 'past_24_hours', 'past_7_days', 'past_30_days'].includes(timeFilter)) {
        throw new Error('timeFilter must be a valid time filter option');
      }
    
      const searchService = (await import('../services/searchService.js')).default;
      
      let results;
      if (searchType === 'news') {
        results = await searchService.searchBingNews(query, maxResults, timeFilter);
      } else {
        results = await searchService.searchBing(query, maxResults);
      }
    
      return {
        tool: 'web_search',
        searchType,
        query,
        maxResults,
        timeFilter: searchType === 'news' ? timeFilter : undefined,
        results: results.results,
        totalResults: results.totalResults,
        timestamp: results.timestamp
      };
    }
  • Input schema definition for the web_search tool, including parameters query, searchType, maxResults, and timeFilter.
    name: 'web_search',
    description: 'Perform web or news search using Bing search engine. Supports both general web search and news search modes.',
    inputSchema: {
      type: 'object',
      properties: {
        query: {
          type: 'string',
          description: 'Search query, e.g., Node.js tutorial, tech news, political updates, etc.'
        },
        searchType: {
          type: 'string',
          enum: ['web', 'news'],
          description: 'Search type: web (general web search), news (news search) - required'
        },
        maxResults: {
          type: 'number',
          description: 'Maximum number of results',
          default: 10,
          minimum: 1,
          maximum: 20
        },
        timeFilter: {
          type: 'string',
          enum: ['past_hour', 'past_24_hours', 'past_7_days', 'past_30_days'],
          description: 'Time filter (only valid for news search): past 1 hour, 24 hours, 7 days, 30 days',
          default: 'past_24_hours'
        }
      },
      required: ['query', 'searchType']
    }
  • Switch case registration that maps tool call 'web_search' to the handleWebSearch function.
    case 'web_search':
      result = await handleWebSearch(args);
  • Core implementation of Bing web search using Puppeteer browser automation to scrape search results.
    async searchBing(query, maxResults = 10) {
      try {
        const browser = await this.initBrowser();
        const page = await browser.newPage();
    
        await page.setUserAgent(this.getRandomUserAgent());
        await page.setViewport({ width: 1920, height: 1080 });
    
        const searchUrl = `https://www.bing.com/search?q=${encodeURIComponent(query)}&count=${maxResults}`;
        await page.goto(searchUrl, { waitUntil: 'networkidle2' });
    
        await page.waitForSelector('#b_results', { timeout: 10000 });
    
        const rawResults = await page.evaluate(() => {
          const searchResults = [];
          const resultElements = document.querySelectorAll('#b_results .b_algo');
    
          resultElements.forEach((element, index) => {
            if (index >= 10) return;
    
            const titleElement = element.querySelector('h2 a');
            const snippetElement = element.querySelector('.b_caption p');
    
            if (titleElement) {
              searchResults.push({
                title: titleElement.textContent.trim(),
                url: titleElement.href,
                snippet: snippetElement ? snippetElement.textContent.trim() : '',
                rank: index + 1
              });
            }
          });
    
          return searchResults;
        });
    
        // Clean URLs in Node.js
        const results = rawResults.map(item => ({
          ...item,
          url: this.cleanUrl(item.url)
        }));
    
        await page.close();
        logger.info(`Bing search completed for query: "${query}", found ${results.length} results`);
    
        return {
          engine: 'Bing',
          query,
          results,
          totalResults: results.length,
          timestamp: new Date().toISOString()
        };
    
      } catch (error) {
        logger.error('Bing search error:', error);
        throw new Error(`Bing search failed: ${error.message}`);
      }
    }
  • Core implementation of Bing news search with time filtering using Puppeteer to handle dynamic news results.
    async searchBingNews(query, maxResults = 10, timeFilter = 'past_24_hours') {
      try {
        const browser = await this.initBrowser();
        const page = await browser.newPage();
    
        await page.setUserAgent(this.getRandomUserAgent());
        await page.setViewport({ width: 1920, height: 1080 });
    
        // Build news search URL
        let searchUrl = `https://www.bing.com/news/search?q=${encodeURIComponent(query)}`;
    
        // Add time filter
        const timeParams = {
          'past_hour': '&qft=interval%3d"1"',
          'past_24_hours': '&qft=interval%3d"24"',
          'past_7_days': '&qft=interval%3d"7"',
          'past_30_days': '&qft=interval%3d"30"'
        };
    
        if (timeParams[timeFilter]) {
          searchUrl += timeParams[timeFilter];
        }
    
        logger.info(`Navigating to Bing News: ${searchUrl}`);
        await page.goto(searchUrl, { waitUntil: 'networkidle2', timeout: 15000 });
    
        // Wait for news results to load
        await new Promise(resolve => setTimeout(resolve, 3000));
    
        // Try to wait for page content
        try {
          await page.waitForSelector('body', { timeout: 5000 });
        } catch (error) {
          logger.warn('Timeout waiting for page load, continuing');
        }
    
        const rawResults = await page.evaluate((maxResults) => {
          const newsResults = [];
    
          // Try multiple selectors for news items
          const selectors = [
            '.news-card',
            '.news-item',
            '.news-card-container',
            '[data-news-card]',
            '.news-content',
            '.news-title',
            '.news-item-container',
            '.news-list-item'
          ];
    
          let newsElements = [];
          for (const selector of selectors) {
            newsElements = document.querySelectorAll(selector);
            if (newsElements.length > 0) {
              break;
            }
          }
    
          // Fallback: try links containing /news/
          if (newsElements.length === 0) {
            const allLinks = document.querySelectorAll('a[href*="/news/"]');
            newsElements = Array.from(allLinks).map(link => {
              const container = link.closest('div') || link.parentElement;
              return container || link;
            });
          }
    
          // Fallback: just take some links
          if (newsElements.length === 0) {
            const allLinks = document.querySelectorAll('a[href]');
            newsElements = Array.from(allLinks).slice(0, 20);
          }
    
          // Extract news info
          newsElements.forEach((element, index) => {
            if (index >= maxResults) return;
    
            let title = '';
            let url = '';
            let source = '';
            let time = '';
    
            // Title
            const titleSelectors = ['h2', 'h3', '.news-title', '.title', 'a'];
            for (const selector of titleSelectors) {
              const el = element.querySelector(selector);
              if (el && el.textContent.trim()) {
                title = el.textContent.trim();
                if (el.href) {
                  url = el.href;
                }
                break;
              }
            }
    
            // Link
            if (!url) {
              const linkEl = element.querySelector('a[href]');
              if (linkEl && linkEl.href) {
                url = linkEl.href;
              }
            }
    
            // Source
            const sourceSelectors = ['.news-source', '.source', '.publisher', '.author'];
            for (const selector of sourceSelectors) {
              const el = element.querySelector(selector);
              if (el && el.textContent.trim()) {
                source = el.textContent.trim();
                break;
              }
            }
    
            // Time
            const timeSelectors = ['.news-time', '.time', '.date', '.timestamp'];
            for (const selector of timeSelectors) {
              const el = element.querySelector(selector);
              if (el && el.textContent.trim()) {
                time = el.textContent.trim();
                break;
              }
            }
    
            // Validate
            if (title && url) {
              const isValidNewsUrl = url.includes('/news/') ||
                url.includes('news') ||
                url.includes('bing.com') ||
                url.includes('msn.com') ||
                url.includes('baidu.com') ||
                url.includes('baike.baidu.com');
    
              if (isValidNewsUrl) {
                newsResults.push({
                  title,
                  url,
                  source,
                  time,
                  rank: index + 1
                });
              }
            }
          });
    
          return newsResults;
        }, maxResults);
    
        // Clean URLs in Node.js
        const results = rawResults.map(item => ({
          ...item,
          url: this.cleanUrl(item.url)
        }));
    
        await page.close();
        logger.info(`Bing News search completed for query: "${query}", found ${results.length} results`);
    
        return {
          engine: 'Bing News',
          query,
          results,
          totalResults: results.length,
          timeFilter,
          timestamp: new Date().toISOString()
        };
    
      } catch (error) {
        logger.error('Bing News search error:', error);
        throw new Error(`Bing News search failed: ${error.message}`);
      }
    }
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the search engine (Bing) and modes (web/news), but lacks critical details such as rate limits, authentication requirements, result format, pagination, or any constraints beyond what's in the schema. For a search tool with zero annotation coverage, this is insufficient.

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 in a single sentence, efficiently stating the core functionality. Every word earns its place, with no redundant information. It could be slightly improved by adding a brief second sentence for behavioral context, but it's well-structured as is.

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 (search with multiple modes and parameters), no annotations, and no output schema, the description is incomplete. It doesn't explain what the tool returns (e.g., search results format, links, snippets) or address behavioral aspects like error handling. This leaves significant gaps for an AI agent to use the tool effectively.

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 all parameters thoroughly. The description adds minimal value beyond the schema by mentioning 'Bing search engine' and 'general web search and news search modes,' but doesn't provide additional semantic context for parameters like query formulation tips or timeFilter applicability. Baseline 3 is appropriate when schema does the heavy lifting.

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: 'Perform web or news search using Bing search engine.' It specifies the action (search), resource (web/news), and engine (Bing). However, it doesn't explicitly differentiate from sibling tools like 'batch_webpage_scrape' or 'get_webpage_content', which appear to be for retrieving specific pages rather than searching.

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 context by mentioning 'general web search and news search modes,' but it doesn't provide explicit guidance on when to use this tool versus the sibling tools. There's no mention of alternatives or exclusions, leaving the agent to infer based on tool names alone.

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/yc9yc/spider-mcp'

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