Skip to main content
Glama
JayceeTran1995

Firecrawl MCP Server

firecrawl_search

Search the web and extract content from results to find specific information across multiple websites when you don't know which site has the data.

Instructions

Search the web and optionally extract content from search results. This is the most powerful web search tool available, and if available you should always default to using this tool for any web search needs.

The query also supports search operators, that you can use if needed to refine the search:

Operator

Functionality

Examples

""

Non-fuzzy matches a string of text

"Firecrawl"

-

Excludes certain keywords or negates other operators

-bad, -site:firecrawl.dev

site:

Only returns results from a specified website

site:firecrawl.dev

inurl:

Only returns results that include a word in the URL

inurl:firecrawl

allinurl:

Only returns results that include multiple words in the URL

allinurl:git firecrawl

intitle:

Only returns results that include a word in the title of the page

intitle:Firecrawl

allintitle:

Only returns results that include multiple words in the title of the page

allintitle:firecrawl playground

related:

Only returns results that are related to a specific domain

related:firecrawl.dev

imagesize:

Only returns images with exact dimensions

imagesize:1920x1080

larger:

Only returns images larger than specified dimensions

larger:1920x1080

Best for: Finding specific information across multiple websites, when you don't know which website has the information; when you need the most relevant content for a query. Not recommended for: When you need to search the filesystem. When you already know which website to scrape (use scrape); when you need comprehensive coverage of a single website (use map or crawl. Common mistakes: Using crawl or map for open-ended questions (use search instead). Prompt Example: "Find the latest research papers on AI published in 2023." Sources: web, images, news, default to web unless needed images or news. Scrape Options: Only use scrapeOptions when you think it is absolutely necessary. When you do so default to a lower limit to avoid timeouts, 5 or lower. Optimal Workflow: Search first using firecrawl_search without formats, then after fetching the results, use the scrape tool to get the content of the relevantpage(s) that you want to scrape

Usage Example without formats (Preferred):

{
  "name": "firecrawl_search",
  "arguments": {
    "query": "top AI companies",
    "limit": 5,
    "sources": [
      "web"
    ]
  }
}

Usage Example with formats:

{
  "name": "firecrawl_search",
  "arguments": {
    "query": "latest AI research papers 2023",
    "limit": 5,
    "lang": "en",
    "country": "us",
    "sources": [
      "web",
      "images",
      "news"
    ],
    "scrapeOptions": {
      "formats": ["markdown"],
      "onlyMainContent": true
    }
  }
}

Returns: Array of search results (with optional scraped content).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes
limitNo
tbsNo
filterNo
locationNo
sourcesNo
scrapeOptionsNo

Implementation Reference

  • The execute handler for the firecrawl_search tool, which uses the Firecrawl client to perform the search, cleans options, logs the query, and returns the result as JSON string.
    execute: async (
      args: unknown,
      { session, log }: { session?: SessionData; log: Logger }
    ): Promise<string> => {
      const client = getClient(session);
      const { query, ...opts } = args as Record<string, unknown>;
      const cleaned = removeEmptyTopLevel(opts as Record<string, unknown>);
      log.info('Searching', { query: String(query) });
      const res = await client.search(query as string, {
        ...(cleaned as any),
        origin: ORIGIN,
      });
      return asText(res);
    },
  • Zod schema defining the input parameters for firecrawl_search, including query, limit, sources, and optional scrapeOptions referencing the shared scrapeParamsSchema.
    parameters: z.object({
      query: z.string().min(1),
      limit: z.number().optional(),
      tbs: z.string().optional(),
      filter: z.string().optional(),
      location: z.string().optional(),
      sources: z
        .array(z.object({ type: z.enum(['web', 'images', 'news']) }))
        .optional(),
      scrapeOptions: scrapeParamsSchema.omit({ url: true }).partial().optional(),
    }),
  • Shared scrapeParamsSchema used by firecrawl_search via scrapeOptions for configuring scraping behavior on search results.
    const scrapeParamsSchema = z.object({
      url: z.string().url(),
      formats: z
        .array(
          z.union([
            z.enum([
              'markdown',
              'html',
              'rawHtml',
              'screenshot',
              'links',
              'summary',
              'changeTracking',
              'branding',
            ]),
            z.object({
              type: z.literal('json'),
              prompt: z.string().optional(),
              schema: z.record(z.string(), z.any()).optional(),
            }),
            z.object({
              type: z.literal('screenshot'),
              fullPage: z.boolean().optional(),
              quality: z.number().optional(),
              viewport: z
                .object({ width: z.number(), height: z.number() })
                .optional(),
            }),
          ])
        )
        .optional(),
      parsers: z
        .array(
          z.union([
            z.enum(['pdf']),
            z.object({
              type: z.enum(['pdf']),
              maxPages: z.number().int().min(1).max(10000).optional(),
            }),
          ])
        )
        .optional(),
      onlyMainContent: z.boolean().optional(),
      includeTags: z.array(z.string()).optional(),
      excludeTags: z.array(z.string()).optional(),
      waitFor: z.number().optional(),
      ...(SAFE_MODE
        ? {}
        : {
            actions: z
              .array(
                z.object({
                  type: z.enum(allowedActionTypes),
                  selector: z.string().optional(),
                  milliseconds: z.number().optional(),
                  text: z.string().optional(),
                  key: z.string().optional(),
                  direction: z.enum(['up', 'down']).optional(),
                  script: z.string().optional(),
                  fullPage: z.boolean().optional(),
                })
              )
              .optional(),
          }),
      mobile: z.boolean().optional(),
      skipTlsVerification: z.boolean().optional(),
      removeBase64Images: z.boolean().optional(),
      location: z
        .object({
          country: z.string().optional(),
          languages: z.array(z.string()).optional(),
        })
        .optional(),
      storeInCache: z.boolean().optional(),
      maxAge: z.number().optional(),
    });
  • src/index.ts:360-360 (registration)
    Tool registration within server.addTool call specifying the name 'firecrawl_search'.
    name: 'firecrawl_search',
  • Helper function getClient used in the handler to create and return the FirecrawlApp client instance based on session and env.
    function getClient(session?: SessionData): FirecrawlApp {
      // For cloud service, API key is required
      if (process.env.CLOUD_SERVICE === 'true') {
        if (!session || !session.firecrawlApiKey) {
          throw new Error('Unauthorized');
        }
        return createClient(session.firecrawlApiKey);
      }
    
      // For self-hosted instances, API key is optional if FIRECRAWL_API_URL is provided
      if (
        !process.env.FIRECRAWL_API_URL &&
        (!session || !session.firecrawlApiKey)
      ) {
        throw new Error(
          'Unauthorized: API key is required when not using a self-hosted instance'
        );
      }
    
      return createClient(session?.firecrawlApiKey);
    }
Behavior4/5

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

With no annotations provided, the description carries full burden and delivers substantial behavioral context: it explains the tool's power level ('most powerful'), recommends default usage, discloses search operators, warns about scrapeOptions timeouts, describes return format ('Array of search results'), and provides workflow guidance. It doesn't mention rate limits or authentication requirements, but covers most behavioral aspects well.

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

Conciseness3/5

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

The description is well-structured with clear sections (Best for, Not recommended, Common mistakes, etc.) and usage examples, but is quite lengthy with operator tables and multiple JSON examples. While informative, it could be more concise by reducing redundancy in examples or combining related guidance sections.

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

Completeness4/5

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

For a complex tool with 7 parameters, 0% schema coverage, no annotations, and no output schema, the description provides substantial context: purpose, usage guidelines, behavioral traits, parameter guidance, examples, and return format. It doesn't fully document all parameters or provide detailed output schema, but gives enough context for effective use given the tool's complexity.

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

Parameters4/5

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

With 0% schema description coverage and 7 parameters, the description compensates well: it explains query parameter supports search operators with a detailed table, mentions limit parameter in examples, describes sources parameter options and defaults, provides guidance on scrapeOptions usage, and shows comprehensive usage examples. It doesn't cover all 7 parameters (tbs, filter, location missing), but adds significant value beyond the bare schema.

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 explicitly states 'Search the web and optionally extract content from search results' - a specific verb+resource combination. It distinguishes from siblings by stating this is 'the most powerful web search tool' and should be default for web searches, differentiating from scrape, map, and crawl tools mentioned later.

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

Usage Guidelines5/5

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

The description provides extensive guidance with dedicated sections: 'Best for' (finding information across multiple websites, most relevant content), 'Not recommended for' (filesystem search, known websites, comprehensive single-site coverage), 'Common mistakes' (using crawl/map for open-ended questions), and 'Optimal Workflow' (search first, then scrape). This explicitly tells when to use this tool vs 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/JayceeTran1995/firecrawl-mcp-server'

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