firecrawl-mcp 3.32.0 → 3.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +47 -5
- package/dist/origin.js +46 -5
- package/dist/server.d.ts +9 -0
- package/dist/server.js +46 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
# Firecrawl MCP Server
|
|
10
10
|
|
|
11
|
-
A Model Context Protocol (MCP) server that brings [Firecrawl](https://github.com/firecrawl/firecrawl) to MCP-compatible
|
|
11
|
+
A Model Context Protocol (MCP) server that brings [Firecrawl](https://github.com/firecrawl/firecrawl), the context API for AI agents, to MCP-compatible clients: search, scrape, and interact with the live web and get back clean Markdown or structured data.
|
|
12
12
|
|
|
13
13
|
> Big thanks to [@vrknetha](https://github.com/vrknetha), [@knacklabs](https://www.knacklabs.ai) for the initial implementation!
|
|
14
14
|
|
package/dist/index.js
CHANGED
|
@@ -2637,25 +2637,64 @@ function initializeClientSlug(name2) {
|
|
|
2637
2637
|
const slug = slugOf(name2);
|
|
2638
2638
|
return isOwnSlug(slug) || GENERIC_CLIENT_NAMES.has(slug) ? "" : slug;
|
|
2639
2639
|
}
|
|
2640
|
-
function
|
|
2641
|
-
let
|
|
2640
|
+
function publicHost(url) {
|
|
2641
|
+
let parsed;
|
|
2642
2642
|
try {
|
|
2643
|
-
|
|
2643
|
+
parsed = new URL(url ?? "");
|
|
2644
2644
|
} catch {
|
|
2645
2645
|
return "";
|
|
2646
2646
|
}
|
|
2647
|
+
const host = parsed.hostname.toLowerCase().replace(/\.$/, "");
|
|
2647
2648
|
if (!host.includes(".") || host.endsWith(".localhost") || host.endsWith(".local") || /^[\d.]+$/.test(host) || host.startsWith("[")) {
|
|
2648
2649
|
return "";
|
|
2649
2650
|
}
|
|
2650
|
-
return
|
|
2651
|
+
return host.replace(/^www\./, "");
|
|
2652
|
+
}
|
|
2653
|
+
function referrerSlug(referrer) {
|
|
2654
|
+
return slugOf(publicHost(referrer));
|
|
2655
|
+
}
|
|
2656
|
+
var SHARED_STATIC_HOSTS = [
|
|
2657
|
+
"github.io",
|
|
2658
|
+
"gitlab.io",
|
|
2659
|
+
"pages.dev",
|
|
2660
|
+
"netlify.app",
|
|
2661
|
+
"vercel.app"
|
|
2662
|
+
];
|
|
2663
|
+
function isHttpUrl(value) {
|
|
2664
|
+
try {
|
|
2665
|
+
return /^https?:$/.test(new URL(value ?? "").protocol);
|
|
2666
|
+
} catch {
|
|
2667
|
+
return false;
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
function oauthClientSlug(clientId, clientName) {
|
|
2671
|
+
if (!isHttpUrl(clientId)) return initializeClientSlug(clientName);
|
|
2672
|
+
const host = publicHost(clientId);
|
|
2673
|
+
if (!host || host === "firecrawl.dev" || host.endsWith(".firecrawl.dev")) {
|
|
2674
|
+
return "";
|
|
2675
|
+
}
|
|
2676
|
+
if (!SHARED_STATIC_HOSTS.some(
|
|
2677
|
+
(shared) => host === shared || host.endsWith(`.${shared}`)
|
|
2678
|
+
)) {
|
|
2679
|
+
return slugOf(host);
|
|
2680
|
+
}
|
|
2681
|
+
const [first = ""] = new URL(clientId ?? "").pathname.split("/").filter(Boolean);
|
|
2682
|
+
const segment = slugOf(first).slice(0, NAME_MAX / 2);
|
|
2683
|
+
if (!segment) return slugOf(host);
|
|
2684
|
+
const room = NAME_MAX - segment.length - 1;
|
|
2685
|
+
return slugOf(`${slugOf(host).slice(0, room)}-${segment}`);
|
|
2651
2686
|
}
|
|
2652
2687
|
function originForClient(client, serverVersion2, userAgent, signals = {}) {
|
|
2653
2688
|
const declared = slugOf(signals.declaredOrigin);
|
|
2654
2689
|
const slug = slugOf(client?.name);
|
|
2655
2690
|
const product = userAgentProduct(userAgent);
|
|
2656
2691
|
const remembered = initializeClientSlug(signals.initializeClient?.name);
|
|
2692
|
+
const oauthClient = oauthClientSlug(
|
|
2693
|
+
signals.oauthClientId,
|
|
2694
|
+
signals.oauthClientName
|
|
2695
|
+
);
|
|
2657
2696
|
const referrer = referrerSlug(signals.referrer);
|
|
2658
|
-
const base = !isOwnSlug(declared) ? `mcp-${declared}` : !isOwnSlug(slug) ? `mcp-${slug}` : product && !RUNTIME_PRODUCTS.has(product) ? `mcp-ua-${product}` : remembered ? `mcp-${remembered}` : referrer ? `mcp-ref-${referrer}` : product ? `mcp-ua-${product}` : ORIGIN_SERVER;
|
|
2697
|
+
const base = !isOwnSlug(declared) ? `mcp-${declared}` : !isOwnSlug(slug) ? `mcp-${slug}` : product && !RUNTIME_PRODUCTS.has(product) ? `mcp-ua-${product}` : remembered ? `mcp-${remembered}` : oauthClient ? `mcp-oauth-${oauthClient}` : referrer ? `mcp-ref-${referrer}` : product ? `mcp-ua-${product}` : ORIGIN_SERVER;
|
|
2659
2698
|
return serverVersion2 ? `${base}@${serverVersion2}` : base;
|
|
2660
2699
|
}
|
|
2661
2700
|
function originHeaders(origin) {
|
|
@@ -2672,6 +2711,8 @@ function requestOrigin(client, session) {
|
|
|
2672
2711
|
{
|
|
2673
2712
|
declaredOrigin: session?.clientOrigin,
|
|
2674
2713
|
initializeClient: session?.initializeClient,
|
|
2714
|
+
oauthClientId: session?.oauthClientId,
|
|
2715
|
+
oauthClientName: session?.oauthClientName,
|
|
2675
2716
|
referrer: session?.clientReferrer
|
|
2676
2717
|
}
|
|
2677
2718
|
);
|
|
@@ -6222,6 +6263,7 @@ function credentialMetadata(data) {
|
|
|
6222
6263
|
userId: typeof data.sub === "string" ? data.sub : void 0,
|
|
6223
6264
|
apiKeyId: typeof data.api_key_id === "string" ? data.api_key_id : void 0,
|
|
6224
6265
|
oauthClientId: typeof data.client_id === "string" ? data.client_id : void 0,
|
|
6266
|
+
oauthClientName: typeof data.client_name === "string" ? data.client_name : void 0,
|
|
6225
6267
|
resource: typeof data.aud === "string" ? data.aud : void 0
|
|
6226
6268
|
};
|
|
6227
6269
|
}
|
package/dist/origin.js
CHANGED
|
@@ -59,25 +59,64 @@ function initializeClientSlug(name) {
|
|
|
59
59
|
const slug = slugOf(name);
|
|
60
60
|
return isOwnSlug(slug) || GENERIC_CLIENT_NAMES.has(slug) ? "" : slug;
|
|
61
61
|
}
|
|
62
|
-
function
|
|
63
|
-
let
|
|
62
|
+
function publicHost(url) {
|
|
63
|
+
let parsed;
|
|
64
64
|
try {
|
|
65
|
-
|
|
65
|
+
parsed = new URL(url ?? "");
|
|
66
66
|
} catch {
|
|
67
67
|
return "";
|
|
68
68
|
}
|
|
69
|
+
const host = parsed.hostname.toLowerCase().replace(/\.$/, "");
|
|
69
70
|
if (!host.includes(".") || host.endsWith(".localhost") || host.endsWith(".local") || /^[\d.]+$/.test(host) || host.startsWith("[")) {
|
|
70
71
|
return "";
|
|
71
72
|
}
|
|
72
|
-
return
|
|
73
|
+
return host.replace(/^www\./, "");
|
|
74
|
+
}
|
|
75
|
+
function referrerSlug(referrer) {
|
|
76
|
+
return slugOf(publicHost(referrer));
|
|
77
|
+
}
|
|
78
|
+
var SHARED_STATIC_HOSTS = [
|
|
79
|
+
"github.io",
|
|
80
|
+
"gitlab.io",
|
|
81
|
+
"pages.dev",
|
|
82
|
+
"netlify.app",
|
|
83
|
+
"vercel.app"
|
|
84
|
+
];
|
|
85
|
+
function isHttpUrl(value) {
|
|
86
|
+
try {
|
|
87
|
+
return /^https?:$/.test(new URL(value ?? "").protocol);
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function oauthClientSlug(clientId, clientName) {
|
|
93
|
+
if (!isHttpUrl(clientId)) return initializeClientSlug(clientName);
|
|
94
|
+
const host = publicHost(clientId);
|
|
95
|
+
if (!host || host === "firecrawl.dev" || host.endsWith(".firecrawl.dev")) {
|
|
96
|
+
return "";
|
|
97
|
+
}
|
|
98
|
+
if (!SHARED_STATIC_HOSTS.some(
|
|
99
|
+
(shared) => host === shared || host.endsWith(`.${shared}`)
|
|
100
|
+
)) {
|
|
101
|
+
return slugOf(host);
|
|
102
|
+
}
|
|
103
|
+
const [first = ""] = new URL(clientId ?? "").pathname.split("/").filter(Boolean);
|
|
104
|
+
const segment = slugOf(first).slice(0, NAME_MAX / 2);
|
|
105
|
+
if (!segment) return slugOf(host);
|
|
106
|
+
const room = NAME_MAX - segment.length - 1;
|
|
107
|
+
return slugOf(`${slugOf(host).slice(0, room)}-${segment}`);
|
|
73
108
|
}
|
|
74
109
|
function originForClient(client, serverVersion2, userAgent, signals = {}) {
|
|
75
110
|
const declared = slugOf(signals.declaredOrigin);
|
|
76
111
|
const slug = slugOf(client?.name);
|
|
77
112
|
const product = userAgentProduct(userAgent);
|
|
78
113
|
const remembered = initializeClientSlug(signals.initializeClient?.name);
|
|
114
|
+
const oauthClient = oauthClientSlug(
|
|
115
|
+
signals.oauthClientId,
|
|
116
|
+
signals.oauthClientName
|
|
117
|
+
);
|
|
79
118
|
const referrer = referrerSlug(signals.referrer);
|
|
80
|
-
const base = !isOwnSlug(declared) ? `mcp-${declared}` : !isOwnSlug(slug) ? `mcp-${slug}` : product && !RUNTIME_PRODUCTS.has(product) ? `mcp-ua-${product}` : remembered ? `mcp-${remembered}` : referrer ? `mcp-ref-${referrer}` : product ? `mcp-ua-${product}` : ORIGIN_SERVER;
|
|
119
|
+
const base = !isOwnSlug(declared) ? `mcp-${declared}` : !isOwnSlug(slug) ? `mcp-${slug}` : product && !RUNTIME_PRODUCTS.has(product) ? `mcp-ua-${product}` : remembered ? `mcp-${remembered}` : oauthClient ? `mcp-oauth-${oauthClient}` : referrer ? `mcp-ref-${referrer}` : product ? `mcp-ua-${product}` : ORIGIN_SERVER;
|
|
81
120
|
return serverVersion2 ? `${base}@${serverVersion2}` : base;
|
|
82
121
|
}
|
|
83
122
|
function originHeaders(origin) {
|
|
@@ -94,6 +133,8 @@ function requestOrigin(client, session) {
|
|
|
94
133
|
{
|
|
95
134
|
declaredOrigin: session?.clientOrigin,
|
|
96
135
|
initializeClient: session?.initializeClient,
|
|
136
|
+
oauthClientId: session?.oauthClientId,
|
|
137
|
+
oauthClientName: session?.oauthClientName,
|
|
97
138
|
referrer: session?.clientReferrer
|
|
98
139
|
}
|
|
99
140
|
);
|
package/dist/server.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ type OriginSession = {
|
|
|
35
35
|
clientOrigin?: string;
|
|
36
36
|
clientReferrer?: string;
|
|
37
37
|
initializeClient?: ClientImplementation;
|
|
38
|
+
oauthClientId?: string;
|
|
39
|
+
oauthClientName?: string;
|
|
38
40
|
};
|
|
39
41
|
/**
|
|
40
42
|
* The origin of every request a tool call makes: the call's client, the
|
|
@@ -241,6 +243,13 @@ interface SessionData {
|
|
|
241
243
|
name?: string;
|
|
242
244
|
version?: string;
|
|
243
245
|
};
|
|
246
|
+
/**
|
|
247
|
+
* The OAuth client id the access token was issued to. A metadata URL id
|
|
248
|
+
* names the product; read only when the User-Agent names a runtime.
|
|
249
|
+
*/
|
|
250
|
+
oauthClientId?: string;
|
|
251
|
+
/** The registered name of that client; read when the id is not a URL. */
|
|
252
|
+
oauthClientName?: string;
|
|
244
253
|
authType?: 'api-key' | 'oauth' | 'env' | 'keyless' | 'none';
|
|
245
254
|
/** Admitted, but the supplied credential cannot be used. */
|
|
246
255
|
credentialError?: 'CREDENTIAL_INVALID';
|
package/dist/server.js
CHANGED
|
@@ -2636,25 +2636,64 @@ function initializeClientSlug(name2) {
|
|
|
2636
2636
|
const slug = slugOf(name2);
|
|
2637
2637
|
return isOwnSlug(slug) || GENERIC_CLIENT_NAMES.has(slug) ? "" : slug;
|
|
2638
2638
|
}
|
|
2639
|
-
function
|
|
2640
|
-
let
|
|
2639
|
+
function publicHost(url) {
|
|
2640
|
+
let parsed;
|
|
2641
2641
|
try {
|
|
2642
|
-
|
|
2642
|
+
parsed = new URL(url ?? "");
|
|
2643
2643
|
} catch {
|
|
2644
2644
|
return "";
|
|
2645
2645
|
}
|
|
2646
|
+
const host = parsed.hostname.toLowerCase().replace(/\.$/, "");
|
|
2646
2647
|
if (!host.includes(".") || host.endsWith(".localhost") || host.endsWith(".local") || /^[\d.]+$/.test(host) || host.startsWith("[")) {
|
|
2647
2648
|
return "";
|
|
2648
2649
|
}
|
|
2649
|
-
return
|
|
2650
|
+
return host.replace(/^www\./, "");
|
|
2651
|
+
}
|
|
2652
|
+
function referrerSlug(referrer) {
|
|
2653
|
+
return slugOf(publicHost(referrer));
|
|
2654
|
+
}
|
|
2655
|
+
var SHARED_STATIC_HOSTS = [
|
|
2656
|
+
"github.io",
|
|
2657
|
+
"gitlab.io",
|
|
2658
|
+
"pages.dev",
|
|
2659
|
+
"netlify.app",
|
|
2660
|
+
"vercel.app"
|
|
2661
|
+
];
|
|
2662
|
+
function isHttpUrl(value) {
|
|
2663
|
+
try {
|
|
2664
|
+
return /^https?:$/.test(new URL(value ?? "").protocol);
|
|
2665
|
+
} catch {
|
|
2666
|
+
return false;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
function oauthClientSlug(clientId, clientName) {
|
|
2670
|
+
if (!isHttpUrl(clientId)) return initializeClientSlug(clientName);
|
|
2671
|
+
const host = publicHost(clientId);
|
|
2672
|
+
if (!host || host === "firecrawl.dev" || host.endsWith(".firecrawl.dev")) {
|
|
2673
|
+
return "";
|
|
2674
|
+
}
|
|
2675
|
+
if (!SHARED_STATIC_HOSTS.some(
|
|
2676
|
+
(shared) => host === shared || host.endsWith(`.${shared}`)
|
|
2677
|
+
)) {
|
|
2678
|
+
return slugOf(host);
|
|
2679
|
+
}
|
|
2680
|
+
const [first = ""] = new URL(clientId ?? "").pathname.split("/").filter(Boolean);
|
|
2681
|
+
const segment = slugOf(first).slice(0, NAME_MAX / 2);
|
|
2682
|
+
if (!segment) return slugOf(host);
|
|
2683
|
+
const room = NAME_MAX - segment.length - 1;
|
|
2684
|
+
return slugOf(`${slugOf(host).slice(0, room)}-${segment}`);
|
|
2650
2685
|
}
|
|
2651
2686
|
function originForClient(client, serverVersion2, userAgent, signals = {}) {
|
|
2652
2687
|
const declared = slugOf(signals.declaredOrigin);
|
|
2653
2688
|
const slug = slugOf(client?.name);
|
|
2654
2689
|
const product = userAgentProduct(userAgent);
|
|
2655
2690
|
const remembered = initializeClientSlug(signals.initializeClient?.name);
|
|
2691
|
+
const oauthClient = oauthClientSlug(
|
|
2692
|
+
signals.oauthClientId,
|
|
2693
|
+
signals.oauthClientName
|
|
2694
|
+
);
|
|
2656
2695
|
const referrer = referrerSlug(signals.referrer);
|
|
2657
|
-
const base = !isOwnSlug(declared) ? `mcp-${declared}` : !isOwnSlug(slug) ? `mcp-${slug}` : product && !RUNTIME_PRODUCTS.has(product) ? `mcp-ua-${product}` : remembered ? `mcp-${remembered}` : referrer ? `mcp-ref-${referrer}` : product ? `mcp-ua-${product}` : ORIGIN_SERVER;
|
|
2696
|
+
const base = !isOwnSlug(declared) ? `mcp-${declared}` : !isOwnSlug(slug) ? `mcp-${slug}` : product && !RUNTIME_PRODUCTS.has(product) ? `mcp-ua-${product}` : remembered ? `mcp-${remembered}` : oauthClient ? `mcp-oauth-${oauthClient}` : referrer ? `mcp-ref-${referrer}` : product ? `mcp-ua-${product}` : ORIGIN_SERVER;
|
|
2658
2697
|
return serverVersion2 ? `${base}@${serverVersion2}` : base;
|
|
2659
2698
|
}
|
|
2660
2699
|
function originHeaders(origin) {
|
|
@@ -2671,6 +2710,8 @@ function requestOrigin(client, session) {
|
|
|
2671
2710
|
{
|
|
2672
2711
|
declaredOrigin: session?.clientOrigin,
|
|
2673
2712
|
initializeClient: session?.initializeClient,
|
|
2713
|
+
oauthClientId: session?.oauthClientId,
|
|
2714
|
+
oauthClientName: session?.oauthClientName,
|
|
2674
2715
|
referrer: session?.clientReferrer
|
|
2675
2716
|
}
|
|
2676
2717
|
);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firecrawl-mcp",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "MCP server for
|
|
3
|
+
"version": "3.33.0",
|
|
4
|
+
"description": "Firecrawl MCP server, the context API for AI agents: search, scrape, parse, crawl, map, and interact with the web, run Agent and Monitor jobs, and search scientific papers (PubMed, bioRxiv, medRxiv, arXiv). Works with Firecrawl cloud or a self-hosted instance.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"mcpName": "io.github.firecrawl/firecrawl-mcp-server",
|
|
7
7
|
"bin": {
|