A side-by-side look at the Pexafy and Firecrawl MCP Server MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Pexafy for search & data extraction work over a hosted endpoint; choose Firecrawl MCP Server for search & data extraction as a local process. You can also run both side by side in one mcpServers block.
search_photos, search_photos_by_image, get_photo_file_by_photo_id.FIRECRAWL_API_KEY.firecrawl_scrape, firecrawl_map, firecrawl_search.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Search & Data Extraction | Search & Data Extraction |
| Quality signal | 56/100 · Good | 90/100 · Excellent |
| Install command | Confirmed | Confirmed |
| Transport | Remote HTTP/SSE | Local subprocess (stdio) |
| Auth | Not declared | API key required |
| Pricing | Not declared | Freemium |
| Required env vars | None listed | FIRECRAWL_API_KEY |
| Verified owner | Community listing | Verified |
| GitHub stars | 0 | 7,603 |
| Directory activity | 0 views 0 installs 0 upvotes | 10 views 0 installs 0 upvotes |
| Tools | 5 | 25 |
| Full listing | View Pexafy | View Firecrawl MCP Server |
search_photosUse this when the user asks for a real photograph, or states a need that a photograph fills, and the picture is not already in the conversation.
Call it when they ask outright: “find me photos of…”, “show me images of…”, “I need a picture of…”, “do you have a photo of…”, “where can I find free photos of…”, in any language.
Call it when they describe the need without asking to search: “I'm writing an article and need a header image”, “my landing page needs a hero image”, “I need something to illustrate this”.
Call it when they ask for something meant to carry photographs: “write an article with pictures”, “a deck with images”.
Call it when they name only the picture, with no reason given: “a photo of a white mug”, “a train in Japan”.
If the user is working on something that usually carries photographs — an article, a page, a deck, a post — without asking for any, you may offer to look for some; call it only once they accept.
This covers requests for photographs for articles, blog posts, websites, landing pages, products, slides, documents, reports, social posts, ads, newsletters, banners, thumbnails, covers, posters, backgrounds, wallpapers and mood boards; photographs that illustrate a concept, explain a subject or accompany a piece of writing; and any request for free, stock, royalty-free, commercially usable, real or documentary photographs.
A request for a visual is not always a request for a photograph: this tool finds photographs that already exist — not illustrations, drawings, logos, icons, diagrams or screenshots — and it does not generate, edit or upscale an image, nor look for a named person.
It searches Pexafy's own index of millions of free-to-use photographs from stock libraries such as Unsplash, Pexels and Pixabay, matched to the scene described. Each result carries a `rank`, a `photo_id`, its licence, the credit line to display and an image link; the file itself comes from get_photo_file_by_photo_id. In a host that renders it, the grid shows them; the answer omits image links.search_photos_by_imageUse this when the user wants photographs that look like a picture, rather than ones described in words: a picture they link to, one the host passes to the tool as a file, or a Pexafy photo already found or liked in the grid.
Call it for “find images like this”, “something similar to this photo”, “find a free alternative to this image”, “I need this but royalty-free”, “photos in this style”, “more like the second one”, whether or not they say “search by image”.
Give exactly one reference: `photo_id` for a Pexafy photo from an earlier result or liked in the grid; `image_url` for a picture at a public URL, such as a link the user pasted; `image_file` when the host passes the user's uploaded image to the tool; `image_base64` for image bytes a client already holds. Sending two is refused. A picture that is only visible in the conversation — not linked, not passed to the tool — is not a reference this tool can receive; its scene can be searched in words with `search_photos`. Words are optional, in `english_search_sentence`: with a `photo_id`, the words that photograph was found under; with an image, only what the user wants changed or kept (“like this but at night”).
It finds free stock photographs in Pexafy's index that visually match the reference. The reference image is sent to Pexafy only to run the search; it is not stored. Each result carries a `rank`, a `photo_id`, its licence, the credit line to display and an image link. In a host that renders it, the grid shows them; the answer omits image links.get_photo_file_by_photo_idReturns one photograph from an earlier Pexafy result as an image file, identified by its `photo_id`. A result's link points to the image; this tool returns the image itself, so the person does not need to send the photograph again.
Use it when the user wants a photograph found here as a file: to place it in a document, a slide or a post, to attach, send or download it, or to have it cropped, captioned or otherwise edited with the host's own tools.
It is for a photograph the person picked: where the Pexafy grid is shown, the photographs of a search are already on screen and need no file to be seen.
The answer contains the photograph, at most 1280 pixels wide, and a line giving its file name, size, licence, source, `photo_id`, page at the source and the credit line to display. One photo per call; the file stays in the conversation afterwards.
This server does not edit images: what can be done to the file next depends on the host's own tools. Its licence and credit line apply to this photograph only.get_grid_selected_photosReturns the photographs the person liked (hearted) in the Pexafy results grid. Use it when the person refers to that selection rather than asking for new photos — for example “the images I selected”, “the ones I chose”, “my selection”, “the photos I hearted”, “the photos I liked”, “use the ones I picked”, “put my selection in the document”, “download the ones I chose”, or “write the article around my photos”.
The selection is held by the grid and the server, not by the conversation: this tool is how it is read, and search results are not the selection. It takes no arguments and returns every liked photograph with its rank, photo_id, photographer, source library, licence, pixel size, orientation, description, page URL and credit line, and `selection_count`, the number of them.
To get one of them as an image file, pass its photo_id to get_photo_file_by_photo_id.
`rank` is the person's order, #1 first: the order the photos were liked in, unless the person rearranged them by dragging in the grid. Where the grid is rendered, that number is drawn on each liked photograph, so it is the number the person sees and names them by (“#2”). The `rank` of a search result is only its position in that answer and is not drawn on the grid.
An empty selection means nothing is liked in the grid currently on screen; a photograph is liked with the heart on it. A selection expires an hour after its last change, and a new search replaces the grid it belongs to.connect_accountAsks the host to offer its own flow for connecting a Pexafy account, when none is attached. Use it when the person asks to connect, link or sign in to a Pexafy account — including from the account button in the Pexafy grid — or wants more searches than the daily allowance available without an account.
When no account is attached, it returns an error result that carries an account-connection request for the host: the error is how that request is delivered, not a failure. A host that supports it shows its own account-connection prompt, which the person completes or dismisses; other hosts show only the result's text. Calling it again returns the same request. When an account is already attached, it says so and starts nothing.
It does not search, and searching does not require calling it. `check_only` is set by the Pexafy grid to read the state without opening a prompt; leave it unset when the person wants to connect or sign in.firecrawl_scrape
Retrieve and extract content from one supplied URL through Firecrawl. Use this when the request identifies a page and needs its content or defined fields. It can return markdown, HTML, links, screenshots, branding data, a targeted answer, or JSON matching a supplied schema; JSON is useful when the requested result has defined fields, while markdown preserves readable page content.
This tool operates on a known page. For a set of pages use `firecrawl_crawl`, and to discover page URLs use `firecrawl_map` or `firecrawl_search`. Options include JavaScript render delay, cache age, main-content filtering, PII redaction, and lockdown cache-only retrieval. Browser actions may change the live page when interactive actions are enabled.
Firecrawl may reuse recently indexed content instead of refetching the page, and the reuse window varies by domain. Set `maxAge: 0` to force a live fetch, or a smaller `maxAge` to bound how stale reused content may be. A successful response does not by itself confirm that the state it describes is still current.
Returns the selected content formats and page metadata.
firecrawl_map
Enumerate URLs indexed under one website through Firecrawl without fetching each page's content. Use this when the request asks for a site's URL inventory, when several relevant pages must be located, or when the desired page URL is unknown. An optional `search` term narrows the URL list, while sitemap, subdomain, query-parameter, and result-limit options control coverage.
Returns matching URLs rather than page bodies. Retrieve one page with `firecrawl_scrape`; collect content across multiple pages with `firecrawl_crawl`.
firecrawl_search
Search web, news, or image sources and return ranked results. Operators include quoted phrases, `-term`, `site:host`, `inurl:term`, `intitle:term`, and `related:host`; the set is non-exhaustive. `includeDomains` and `excludeDomains` are mutually exclusive hostname filters; categories limit results to GitHub, research, PDF, or developer sources.
For a programming question, add `categories: ["developer"]`. It searches an index of GitHub issues, merged pull requests, repository READMEs, and curated documentation sites, and returns the hits in `data.developer` beside the web results.
`categories: ["research"]` restricts these web results to research-affiliated websites and returns page snippets. The `firecrawl_research_*` tools are a separate surface that searches paper abstracts and full text across biomedical (PubMed, bioRxiv, medRxiv) and arXiv literature.
`scrapeOptions` can attach extracted page content; pages fetched this way use a fixed reuse window and ignore `maxAge`, so use `firecrawl_scrape` when a live fetch is required. Returns source-type result groups and usage metadata. Authenticated responses can include an `id` for optional search feedback.
Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"pexafy": {
"url": "https://pexafy.com/mcp/"
}
}
}
{
"mcpServers": {
"firecrawl-firecrawl-mcp-server": {
"command": "npx",
"args": [
"-y",
"firecrawl-mcp"
],
"env": {
"FIRECRAWL_API_KEY": "YOUR_FIRECRAWL_API_KEY_HERE"
}
}
}
}
firecrawl_crawl
Start a multi-page crawl at a website URL, poll it to a terminal state, and return the final status and collected data. Scope can be bounded with include/exclude paths, depth, page limit, subdomain/external-link controls, sitemap handling, delay, and scrape options.
Crawl results can be large; use conservative limits when full-site coverage is unnecessary. Webhooks and interactive scrape actions are unavailable in safe mode. Returns the crawl ID, status, and page data.
firecrawl_check_crawl_status
Retrieve the current status, progress, and available results for an existing crawl ID. This only reads Firecrawl job state and does not start or modify the crawl.
firecrawl_extract
Deprecated compatibility entry point. Use firecrawl_scrape once per known URL with formats: ["json"] and jsonOptions containing the prompt and schema. Use firecrawl_search or firecrawl_agent before Scrape when URLs are not known.
firecrawl_agent
Start an asynchronous web research job from a prompt, optional seed URLs, and an optional JSON schema. Use this for a requested synthesis across multiple sources when the task can wait for asynchronous completion. The agent can search, navigate, read pages, and assemble a structured result.
This call returns only a job ID, not the research result. Read the job with `firecrawl_agent_status` until it reaches `completed` or `failed`; research commonly takes several minutes. If the job cannot finish within the task's available time, `firecrawl_search` and `firecrawl_scrape` can gather evidence synchronously.
firecrawl_agent_status
Retrieve progress or final results for a `firecrawl_agent` job ID. A `processing` response is non-terminal and does not contain the final research result. Check again after 15–30 seconds until the status is `completed` or `failed`; complex jobs can take several minutes. If the job cannot finish within the task's available time, use `firecrawl_search` and `firecrawl_scrape` to complete the requested output.
Returns job status, progress information, and result data when completed.
firecrawl_interact
Open or reuse a live browser session to navigate a page, click controls, fill fields, or run browser code. Provide either `url` or `scrapeId`, and either a natural-language `prompt` or executable `code`; code can run as Bash, Python, or Node with a bounded timeout.
This acts on the live site, so actions such as form submission can create persistent external side effects. Returns execution output, stdout/stderr, exit status, and session viewing URLs.
firecrawl_interact_stop
Stop the live interact session associated with a `scrapeId` and release its resources. Returns a success confirmation.
firecrawl_parse
Parse one supported document into markdown, HTML, links, summary, targeted answers, or JSON matching a schema. Supported inputs include common HTML, PDF, Word, RTF, OpenDocument, and spreadsheet files; PDF parsing can be bounded with `pdfOptions.maxPages`.
Local MCP reads `filePath` from the server filesystem. Hosted MCP uses two calls: first provide `filePath` to receive upload instructions, upload locally, then call again with the returned `uploadRef`; do not send both fields together. Remote web URLs belong in `firecrawl_scrape`.
Set `redactPII` to request redaction of personally identifiable information in the returned content. `zeroDataRetention` requires an eligible authenticated account; omit it for anonymous keyless use. Returns upload instructions for hosted phase one or parsed document content for the final call.
firecrawl_monitor_create
Create a recurring scrape, crawl, or search monitor that compares each check with its retained predecessor. The simple form accepts `page`/`pages` or `queries` plus a plain-language `goal`; the advanced `body` form controls targets, schedule, change-tracking formats, judging, retention, webhook, and notifications.
In the simple form, a `goal` is required. If `queries` contains one or more non-empty values and is supplied with `page`/`pages`, `queries` create the search target and page targets are ignored. A monitor schedules future network checks and can send configured email or webhook notifications. Returns the created monitor.